Search code examples
delphi

How to format date in MM/DD/YYYY in Delphi


I have array of string as mentioned below.

Param : array[1..5] of string = ('US','Dollor','27/03/2017','IND','INR');

I need to find the string which contains date and format it in MM/DD/YYYY. To achieve this I am running for loop and passing each string in TryStrToDate. If string is of date type, it will return true and then I will format that string in desired format. My code is as below

 for i := 1 to ParamCount do
  begin
   if TryStrToDate(Param[i],DateValue)=true then
   begin
    Param[i] := DateToStr(StrToDate(Param[i]));
    ShowMessage(Param[i]);
   end;
 end;

Here date in Param[] is in DD/MM/YYYY so TryStrToDate is unable to understand. How can i change the code? After this final result should be as below

Param : array[1..5] of string = ('US','Dollor','03/27/2017','IND','INR');

Used Mark's solution as below:

  GetLocaleFormatSettings(ALocID, AFormatSettings);
  AFormatSettings.ShortDateFormat := 'DD/MM/YYYY';
  for i := 1 to ParamCount do
  begin
    if TryStrToDate(param[i], DateValue, AFormatSettings) = False then
      Continue;
    try
      DateVal := StrToDate(param[i], AFormatSettings);
      param[i] := DateToStr(DateVal);
      Continue;
    except
      Continue;
    end;
  end;

Solution

  • TryStrToDate is a Delphi library function that will try to convert a string into a TDateTime type. In my code there were some formats that I wanted to accept that are not allowed by the TryStrToDate function. To convert those dates if the first method fails I call VarToDateTime. That calls a variant function that supports additional formats.

    As Remy commented there is an option parameter of a TFormatSettings type that allows you some measure of control over the formats accepted. I still needed to use VarToDateTime in order to covert dates that spelled out the month instead of using numeric values.

    var
      DateValue: TDateTime;
    
    for i:= 1 to ParamCount do
    begin
      // If we don't have a valid date see if it looks like a different
      // normal date field.
      if TryStrToDate(Param[i], DateValue) = false then
        continue; 
    
      // If the simple TryStrToDate does not work use the Variants function,
      // there is no "Try" version so catch the error here.
      try
        DateValue := VarToDateTime(Param[i]);
      except
        continue;
      end;
    
      // Use/Reformat DateValue here
     Param[i] := FormatDateTime('MM/DD/YYYY', DateValue);
    end;
    

    Additional Information on using TFormatSettings
    The TFormatSettings parameter can change if a date is interpreted to have the days or the month listed first. If you do not specify a Format Setting you will be using the Operating System Default. TryStrToDate looks at the short date format string to determine what order to expect. It looks at the string format for the first matching letter to decide on acceptable formats:

    case Chr(Ord(DateFormat[I]) and $DF) of
      'E': Result := doYMD;
      'Y': Result := doYMD;
      'M': Result := doMDY;
      'D': Result := doDMY;
    

    Here is a test procedure that can show you the difference. You can create a FormatSettings based on a locale, or you can set the short date format directly.

    procedure TForm7.Button3Click(Sender: TObject);
    var
      s: string;
      d: TDateTime;
      FormatUS: TFormatSettings;
      FormatGB: TFormatSettings;
    begin
      s := '5/10/2017';
    
      Memo1.Lines.Append('Testing GB');
      FormatGB := TFormatSettings.Create('en-GB');
      if TryStrToDate(s, d, FormatGB) = false then
      begin
        Memo1.Lines.Append(s + ' is not a valid date');
      end
      else
      begin
        Memo1.Lines.Append('Found Date: ' + FormatDateTime('dd MMMM YYYY', d));
        // will print: Found Date: 05 October 2017
      end;
    
      Memo1.Lines.Append('');
      Memo1.Lines.Append('Testing US');
      FormatUS := TFormatSettings.Create('en-US');
      if TryStrToDate(s, d, FormatUS) = false then
      begin
        Memo1.Lines.Append(s + ' is not a valid date');
      end
      else
      begin
        Memo1.Lines.Append('Found Date: ' + FormatDateTime('dd MMMM YYYY', d));
      end;
    
      Memo1.Lines.Append('');
      Memo1.Lines.Append('Testing with modified ShortDate Format');
      FormatUS.ShortDateFormat := 'yyyy/mm/dd';
      if TryStrToDate(s, d, FormatUS) = false then
      begin
        Memo1.Lines.Append(s + ' is not a valid date');
      end
      else
      begin
        Memo1.Lines.Append('Found Date: ' + FormatDateTime('dd MMMM YYYY', d));
      end;
    
    end;
    

    The output will show:

    Testing GB
    Found Date: 05 October 2017

    Testing US
    Found Date: 10 May 2017

    Testing with modified ShortDate Format
    5/10/2017 is not a valid date