TDateTime as ISO-Date

Hello,

is there an easy way to get an ISO-date from a TDateTime-property in an object?

If I have an object like

TPerson = class
  date_created: TDateTime;
end;

I can translate this in my schema as a Float.

type Person {
  date_created: Float
}

and I will get in the resulting JSON something like

{
  "data": {
    "person": {
      "date_created": 43068.4026157407
    }
  }
}

But I would like to get it this way:

...
      "date_created": "2022-04-07T20:01:15"
...

Kind regards
Harald

The best way is to use a specific DateTime type and create it so that you control the serialization and parsing. The type would be something like this:

  TSchemaDateTimeType = class(TSchemaScalarType)
  strict protected
    function ParseLiteral(Value: TASTValue): TValue; override;
  public
    constructor Create; reintroduce;
  public
    function ParseValue(const Value: TValue): TValue; override;
    function Serialize(const Value: TValue): TValue; override;
  end;

{ TSchemaDateTimeype }

constructor TSchemaDateTimeType.Create;
begin
  inherited Create('DateTime');
end;

function TSchemaDateTimeType.ParseLiteral(Value: TASTValue): TValue;
var
  DateValue: TDateTime;
begin
  if Value is TASTStringValue then
  begin
    if not TBclUtils.TryISOToDateTime(TASTSTringValue(Value).Value, DateValue) then
      raise EGraphQLCoercingParseLiteral.Create(Self.DisplayName, Value);
    Result := TValue.From<TDateTime>(DateValue);
  end
  else
    raise EGraphQLCoercingParseLiteral.Create(Self.DisplayName, Value);
end;

function TSchemaDateTimeType.ParseValue(const Value: TValue): TValue;
begin
  if (Value.TypeInfo =  System.TypeInfo(TDateTime)) or
    (Value.TypeInfo =  System.TypeInfo(TDate)) or
    (Value.TypeInfo =  System.TypeInfo(TTime)) then
    Result := Value
  else
    raise EGraphQLCoercingParseValue.Create(Self.DisplayName, Value);
end;

function TSchemaDateTimeType.Serialize(const Value: TValue): TValue;
begin
  if Value.IsEmpty then
    Exit(TValue.Empty);

  if not Value.TryCast(TypeInfo(TDateTime), Result) then
    raise EGraphQLCoercingSerialize.Create(Self.DisplayName, Value);

  Result := TBclUtils.DateTimeToISO(Value.AsType<TDateTime>, True);
end;

Then you can register it for all GraphQL schema:

  TSchemaDocument.OnGlobalCreate := 
    procedure RegisterGlobalTypes(Schema: TSchemaDocument);
    begin
      Schema.Add(TSchemaDateTimeType.Create);
    end;

Your schema then can be something like this:

type Person {
  date_created: DateTime
}

Note that the OnGlobalCreate event was introduced in version 1.3.

Hello Wagner,

thank You very much for this great solution. This allows a lot of possibilities for own type definitions.

Kind regards
Harald

1 Like

This topic was automatically closed 60 minutes after the last reply. New replies are no longer allowed.