5

I receive the following JSON from a request:

{
  "cdPlayer": 3,
  "nmPlayer": "Player Name",
  "dtCreate": "2016-08-24T22:53:31.687",
  "dtChange": null,
  "idStatus": true
 }

I would like to load convert dtCreate and dtChange to TDateTime. How to properly do this? There is no TJSONDateTime to cast the GetValue. Below is my current code where I'm casting it to a plain String.

procedure TfrmPrincipal.btnInfoClick(Sender: TObject);
var
  jsonRoot: TJSONObject;
  tokenRequest: TRESTRequest;
  tokenResponse: TRESTResponse;
  tokenClient: TRESTClient;
  tokenAutenticacao: TOAuth2Authenticator;
begin
  tokenClient := TRESTClient.Create(nil);
  tokenRequest := TRESTRequest.Create(nil);
  tokenResponse := TRESTResponse.Create(nil);
  tokenAutenticacao := TOAuth2Authenticator.Create(nil);
  try
    tokenRequest.Client := tokenClient;
    tokenRequest.Response := tokenResponse;
    tokenRequest.Method := TRESTRequestMethod.rmPUT;
    tokenClient.Authenticator := tokenAutenticacao;
    tokenAutenticacao.TokenType := TOAuth2TokenType.ttBEARER;
    tokenAutenticacao.AccessToken := 'token_string';
    tokenClient.BaseURL := 'http://host/url/method';
    tokenRequest.Execute;
    jsonRoot:= TJSONObject.ParseJSONValue(tokenResponse.JSONText) as TJSONObject;
    Memo1.Lines.Add('cdPlayer => ' + jsonRoot.GetValue('cdPlayer').Value);
    Memo1.Lines.Add('nmPlayer=> ' + jsonRoot.GetValue('nmPlayer').Value);
    Memo1.Lines.Add('dtCreate=> ' + jsonRoot.GetValue('dtCreate').Value);
    Memo1.Lines.Add('dtChange=> ' + jsonRoot.GetValue('dtChange').Value);
    Memo1.Lines.Add('idStatus=> ' + (jsonRoot.GetValue('idStatus') as TJSONBool).ToString);
  finally
    tokenAutenticacao.Free;
    tokenResponse.Free;
    tokenRequest.Free;
    tokenClient.Free;
  end;
end;

I'm using Delphi XE 10 Seatle. Thanks

EDIT

As far as the duplicate goes, I had no ideia that this Data format was ISO 8601. That's why I couldn't find the answer anywhere through Google. Maybe my question will help some others that, like me, didn't know as well.

Pascal
  • 2,944
  • 7
  • 49
  • 78
  • I had no ideia this format was ISO 8601. That's why I could find the answer. But Tks – Pascal Sep 10 '16 at 17:27
  • Indeed. Totally understand. Bottom line with date conversion is that almost certainly all questions eating to dates have already been asked. Somehow need to find them! – David Heffernan Sep 10 '16 at 17:34

1 Answers1

5

I would extract each part of the date (year, month, day, hours, minutes, milliseconds) from that string, and encode a datetime value. It's easy because each part is always at the same position.

function JSONDate_To_Datetime(JSONDate: string): TDatetime;
var Year, Month, Day, Hour, Minute, Second, Millisecond: Word;
begin
  Year        := StrToInt(Copy(JSONDate, 1, 4));
  Month       := StrToInt(Copy(JSONDate, 6, 2));
  Day         := StrToInt(Copy(JSONDate, 9, 2));
  Hour        := StrToInt(Copy(JSONDate, 12, 2));
  Minute      := StrToInt(Copy(JSONDate, 15, 2));
  Second      := StrToInt(Copy(JSONDate, 18, 2));
  Millisecond := Round(StrToFloat(Copy(JSONDate, 19, 4)));

  Result := EncodeDateTime(Year, Month, Day, Hour, Minute, Second, Millisecond);
end;
RepeatUntil
  • 2,272
  • 4
  • 32
  • 57
Marc Guillot
  • 6,090
  • 1
  • 15
  • 42
  • Yeah.. I thought about doing that. I just thought that would be a built-in function that did it, and treated the Time Zone as well. – Pascal Sep 10 '16 at 16:00
  • As far as I know there is not an standard JSON date format, so it's not surprising that Delphi doesn't have a TJSONDateTime class. – Marc Guillot Sep 10 '16 at 16:01
  • I see. It is generated from .Net Web API. I`ll give it some time, to see if any other answer pops up. Thank you soo much for your time. – Pascal Sep 10 '16 at 16:04
  • 1
    Marc, a slight correction on your code, just for posperity's sake, it's StrToFloat. :) – Pascal Sep 10 '16 at 16:17
  • Don't reinvent the wheel – David Heffernan Sep 10 '16 at 17:18
  • Worth to mention what "JSONDate" term is bogus because `Date`s are completely outside of JSON specification, unfortunately. – Free Consulting Sep 12 '16 at 00:08
  • If seconds start at 18 and have 2 digits, milliseconds cannot start at 19. Also I cannot see why making the millliseconds a 0 or 1 value with the round, instead of just converting the integer value after the dot to the actual milliseconds. – ciuly Feb 17 '18 at 15:36
  • 1
    Since Delphi XE6 the function System.DateUtils.ISO8601ToDate solves this. See also http://docwiki.embarcadero.com/Libraries/XE6/en/System.DateUtils.ISO8601ToDate – Schneider Infosystems Ltd Jul 29 '21 at 13:17