0

I am building my GraphQL schema for my project and one of my models has a DateTime format.

How do I write out date formats on my GraphQL schema?

I tried DateTime or Date but nothing shows up.

This is the model:

public Integer Id;
public String name;
public String description;
public LocalDate birthDate;

This is what's in my GraphQL schema:

type Pet {
    id: ID!
    name: String!
    description: String
    birthDate: DateTime
} 

But it says:

Unknown type DateTime

andrewJames
  • 19,570
  • 8
  • 19
  • 51
  • 1
    Does this answer your question? [Date and Json in type definition for graphql](https://stackoverflow.com/questions/49693928/date-and-json-in-type-definition-for-graphql) – andrewJames Dec 04 '22 at 21:58
  • Another approach, mentioned in a comment, is to "_directly store dates as time in millis_" (milliseconds since the epoch). Look at Java's [`Instant`](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/time/Instant.html). BUT I don't know if epoch-seconds would fit into a GraphQL primitive - so that may not help. – andrewJames Dec 04 '22 at 22:03

1 Answers1

1

Create a custom scalar for your types that is not recognized by your framework.

I am not sure which graphql-java based framework you are using. I assume you are using the official Spring for GraphQL from Spring team.

  1. Create a custom scalar, eg my LocalDateTime scalar.

    public class LocalDateTimeScalar implements Coercing<LocalDateTime, String> { @Override public String serialize(Object dataFetcherResult) throws CoercingSerializeException { if (dataFetcherResult instanceof LocalDateTime) { return ((LocalDateTime) dataFetcherResult).format(DateTimeFormatter.ISO_DATE_TIME); } else { throw new CoercingSerializeException("Not a valid DateTime"); } }

     @Override
     public LocalDateTime parseValue(Object input) throws CoercingParseValueException {
         return LocalDateTime.parse(input.toString(), DateTimeFormatter.ISO_DATE_TIME);
     }
    
     @Override
     public LocalDateTime parseLiteral(Object input) throws CoercingParseLiteralException {
         if (input instanceof StringValue) {
             return LocalDateTime.parse(((StringValue) input).getValue(), DateTimeFormatter.ISO_DATE_TIME);
         }
    
         throw new CoercingParseLiteralException("Value is not a valid ISO date time");
     }
    

    }

  2. Register it in your custom RuntimeWiring bean, check here.

    public class Scalars {
    
        public static GraphQLScalarType localDateTimeType() {
            return GraphQLScalarType.newScalar()
                    .name("LocalDateTime")
                    .description("LocalDateTime type")
                    .coercing(new LocalDateTimeScalar())
                    .build();
        }
    }
    
    @Component
    @RequiredArgsConstructor
    public class PostsRuntimeWiring implements RuntimeWiringConfigurer {
        private final DataFetchers dataFetchers;
    
        @Override
        public void configure(RuntimeWiring.Builder builder) {
            builder
                    //...
                    .scalar(Scalars.localDateTimeType())
                    //...
                    .build();
        }
    }
    

If you are using Scalars in other graphql-java based frameworks(GraphQL Java, GraphQL Java Kickstart, GraphQL Kotlin, GraphQL SPQR, Netflix DGS etc) and spring integrations, check my Spring GraphQL Sample. The back-end principle is similar, just some different config.

Hantsy
  • 8,006
  • 7
  • 64
  • 109