Skip to content

Add Timestamp scalar (SecondsSinceEpochScalar) #157

Open
@clutcher

Description

@clutcher

Can we extend scalars with additional timestamp scalar?

Something like this:

import graphql.GraphQLContext;
import graphql.execution.CoercedVariables;
import graphql.language.IntValue;
import graphql.language.StringValue;
import graphql.language.Value;
import graphql.schema.Coercing;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAccessor;
import java.util.Locale;

public class TimestampScalar implements Coercing<TemporalAccessor, String> {

    @Override
    public String serialize(Object dataFetcherResult, GraphQLContext graphQLContext, Locale locale) {
        if (!(dataFetcherResult instanceof TemporalAccessor temporalAccessor)) {
            return null;
        }

        switch (temporalAccessor) {
            case Instant instant -> {
                return Long.toString(instant.getEpochSecond());
            }
            case LocalDateTime localDateTime -> {
                return Long.toString(localDateTime.toEpochSecond(ZoneOffset.UTC));
            }
            case ZonedDateTime zonedDateTime -> {
                return Long.toString(zonedDateTime.toEpochSecond());
            }
            case OffsetDateTime offsetDateTime -> {
                return Long.toString(offsetDateTime.toEpochSecond());
            }
            default -> {
                try {
                    Instant instant = Instant.from(temporalAccessor);
                    return Long.toString(instant.getEpochSecond());
                } catch (Exception e) {
                    return null;
                }
            }
        }
    }


    @Override
    public TemporalAccessor parseValue(Object input, GraphQLContext graphQLContext, Locale locale) {
        if (input instanceof Number number) {
            return convertEpochSecondsToTemporal(number.longValue());
        }
        if (input instanceof String string) {
            return convertToTemporal(string);
        }
        return null;
    }

    @Override
    public TemporalAccessor parseLiteral(Value<?> input, CoercedVariables variables, GraphQLContext graphQLContext, Locale locale) {
        if (input instanceof StringValue stringValue) {
            return convertToTemporal(stringValue.getValue());
        }
        if (input instanceof IntValue intValue) {
            try {
                long epochSeconds = intValue.getValue().longValue();
                return Instant.ofEpochSecond(epochSeconds).atZone(ZoneOffset.UTC);
            } catch (Exception _) {
            }
        }
        return null;
    }

    @NotNull
    private static Temporal convertToTemporal(String value) {
        if (StringUtils.isNumeric(value)) {
            long epochSeconds = Long.parseLong(value);
            return Instant.ofEpochSecond(epochSeconds).atZone(ZoneOffset.UTC);
        }

        return Instant.parse(value);
    }

    @NotNull
    private static TemporalAccessor convertEpochSecondsToTemporal(long epochSeconds) {
        return Instant.ofEpochSecond(epochSeconds).atZone(ZoneOffset.UTC);
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions