Search code examples
delphiiso8601delphi-xe6

Is there a Delphi RTL function that can convert the ISO 8601 basic date format to a TDate?


ISO 8601 describes a so called basic date format that does not use the dashes:

20140507 is a valid representation of the more readable 2014-05-07.

Is there a Delphi RTL function that can interpret that basic format and convert it to a TDateTime value?

I tried

function TryIso2Date(const _s: string; out _Date: TDateTime): Boolean;
var
  Settings: TFormatSettings;
begin
  Settings := GetUserDefaultLocaleSettings;
  Settings.DateSeparator := #0;
  Settings.ShortDateFormat := 'yyyymmdd';
  Result := TryStrToDate(_s, Date, Settings);
end;

TryIso2Date('20140507', dt);

but it did not work because the DateSeparator could not be found in the string.

The only solution I so far came up with (other than writing the parsing code myself) is adding the missing dashes before calling TryStrToDate:

function TryIso2Date(const _s: string; out _Date: TDateTime): Boolean;
var
  Settings: TFormatSettings;
  s: string;
begin
  Settings := GetUserDefaultLocaleSettings;
  Settings.DateSeparator := #0;
  Settings.ShortDateFormat := 'yyyy-mm-dd';
  s := Copy(_s,1,4) + '-' + Copy(_s, 5,2) + '-' + Copy(_s, 7);
  Result := TryStrToDate(_s, Date, Settings);
end;

TryIso2Date('20140507', dt);

This works, but it feels rather clumsy.

This is Delphi XE6, so it should have the most recent RTL possible.


Solution

  • You can use Copy to pull out the values as you already do. And then you just need to encode the date:

    function TryIso8601BasicToDate(const Str: string; out Date: TDateTime): Boolean;
    var
      Year, Month, Day: Integer;
    begin
      Assert(Length(Str)=8);
      Result := TryStrToInt(Copy(Str, 1, 4), Year);
      if not Result then
        exit;
      Result := TryStrToInt(Copy(Str, 5, 2), Month);
      if not Result then
        exit;
      Result := TryStrToInt(Copy(Str, 7, 2), Day);
      if not Result then
        exit;
      Result := TryEncodeDate(Year, Month, Day, Date);
    end;