-
Notifications
You must be signed in to change notification settings - Fork 1.1k
[RFC] Support DateTime scalar #315
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Implementation of the DateTime scalar proposed in graphql/graphql-spec#315.
Thanks for opening this! My primary concern with adding this to the spec is just seeing the broad array of types, options, and opinions brought up in graphql/graphql-js#557. If we add this type would we later regret doing so? Would most people simply ignore it in favor of their own preferred time type? I'd like to avoid a situation where a built-in scalar for time fails to handle the cases people expect and results in a multitude of options that explode the common scalar set (like graphql/graphql-js#557 (comment)) James Gorman in that thread had a poignant comment (graphql/graphql-js#557 (comment)) "My personal view that GraphQL should either do nothing or go the whole hog and specify a semantically complete set of temporal types." - I'm curious what you think about this. Should the GraphQL core specification itself just do nothing, and leave the definition of times up to the application/user domain?
My understanding is that a Date scalar would simply be a subset of DateTime. That may be an argument for using a less strict profile than 3339 which allows for the |
To answer your question brought up on the other thread about how times are handled at Facebook: we have a handful of different time representations, but each one is fairly specific to a different application-domain problem. Some examples: The most common is just a unix timestamp. We use these for timezone-less universal time, typically (but not always) for content where the time is not user-visible but instead used for behavior. Though it turns out that knowing a GMT unix timestamp and someone's local time zone can get you pretty far. It's also preferred since it's supported with no additional effort on every platform. Second most common is an ISO 8601 time, though we've ended up building some custom client infrastructure to handle these. These are often used for Facebook Events, or other things where we're not describing time in terms of a physical reality but in terms of a human experience. "Happy hour starts at 5pm" or "Noon" or "Tomorrow" can all be coerced to a specific time, but there is context involved and sometimes not specifying seconds or a timezone, or a date (time only) is actually the desired intent. If this sounds complicated, it is. Third most common is an object type, like There are a couple other long-tail representations that are used in rare cases. They're usually very specific to a certain application problem. |
Thanks for all the exploration in this area! It's really interesting to hear different approaches. Given the range of possible solutions to DateTime/Date/Time issues, I don't think adding a scalar to the spec is worth the complexity. There's such a variety of needs and platform-specific constraints that plenty of folks will roll their own anyways. For my own case, I used an object type so that I could include a type DateTime {
year: Int!
month: Int!
# ...
timeAgo: String!
strftime(format: String!): String!
} |
I agree that this might add more complexity than it reduces. |
@leebyron thanks for explaining how Facebook handles times in more depth. It's great to see so many people sharing their use cases both in this thread and in the graphql-js PR. It does indeed show that the use cases differ greatly between different domains.
This is a good question. I think that the discussions have identified 3 possible ways of looking at this:
Option 1 has the advantage of being 100% complete, however it may also give a lot of overhead to the specification. I think that this will result in the picture you painted @leebyron: "I'd like to avoid a situation where a built-in scalar for time fails to handle the cases people expect and results in a multitude of options that explode the common scalar set". Option 2 is the most flexible. It allows users to define the set of temporal types that fit their use cases exactly. However, I can see a downside in that developers will often have to "reinvent the wheel" when it comes to defining some basic date/time functionality. Developers may inadvertently represent date-time as strings or integers in which case the API does not define a clear contract that client applications can uphold. Option 3 is thee middle-way; prevent the GraphQL specification from becoming bloated with options for representing time by introducing a simple to use DateTime scalar that follows a clear standard. @leebyron I think that your comment in the graphql-js pull request made a good point. "Also I should point out that if we were to write specification for DateTime, it would not remove your ability to use additional types like MonthYear in your servers if that was the right choice for your API." If the default scalar does not cover a specific use case then there is always an escape hatch that allows the user to create a custom scalar if the need arises. But the majority of the developers won't have to think about it and can simply use the default. The question is of course, what DateTime scalar definition would cover 80-90% of the use cases? Does such a scalar even exist or are there so many different domains/use cases that it is impossible to create such a scalar? As was mentioned by @rmosolgo: "There's such a variety of needs and platform-specific constraints that plenty of folks will roll their own anyways." This is a good point highlighting that creating a generic scalar may not be feasible. I think that the discussions in the PRs have given a lot of valuable information about what kinds of issues people are running into. I do agree that adding this to the spec is risky, if specified wrongly then people will simply work around it and use their own solutions which is undesirable, therefore we have to tread carefully! @leebyron what do you think about the above point? Do you see the same 3 options and if so do which do you think is most appropriate for graphql? To clarify, I decided to go with the RFC 3339 profile in this PR because I think it is an example of a simple format that is widely applicable and sets some clear guidelines as to what users can expect to receive; the tradeoff for this simplicity is that it does not cover every use case. I agree that it is worth investigating whether a less constrained profile that includes things like dates (without times) etc. is more appropriate. I think that this is an interesting space to keep investigating given the valuable information contributed by everyone in the discussions over the previous months. |
I'm closing this PR since it's been quite a long time and the explorations which started from this led to the realization that defining a single format for DateTime as a base scalar wasn't able to get consensus due to different requirements. This could be reconsidered in the future if anything changes, but I want to ensure the current set of PRs are being actively addressed. |
I started a new RFC about date/time scalar: #579 |
Following the discussions in graphql-js repo (graphql/graphql-js#557) I would like to submit a proposal for adding a
DateTime
scalar to the GraphQL specification. Adding this to the specification allows us to get some standard behaviour regarding date and time representations in GraphQL.The
DateTime
scalar conforms to the RFC 3339 profile of the ISO 8601 standard. The RFC 3339 standard is very simple to understand and lightweight in contrast to the full ISO 8601 standard, I think it is therefore a good fit for graphql. Quoting the RFC 3339 standard document:”The complete set of date and time formats specified in ISO 8601
[ISO8601] is quite complex in an attempt to provide multiple
representations and partial representations. Appendix A contains an
attempt to translate the complete syntax of ISO 8601 into ABNF.
Internet protocols have somewhat different requirements and
simplicity has proved to be an important characteristic. In
addition, Internet protocols usually need complete specification of
data in order to achieve true interoperability. Therefore, the
complete grammar for ISO 8601 is deemed too complex for most Internet
protocols.”
See the updated PR (graphql/graphql-js#557) in the graphql reference implementation for an implementation of the proposed
DateTime
scalar.Issue with leap seconds
Note, the RFC 3339 profile allows for leap seconds, this is problematic because leap seconds cannot be known in advance and therefore the code will have to be continuously updated over time to take leap seconds into account. The
Date
class in javascript doesn’t accept leap seconds for example in order to avoid these issues. Should we do the same in the specification and explicitly mention that leap seconds are not supported?Thoughts on a Date scalar
Next to a
DateTime
scalar I have also had many use cases for aDate
scalar (used to represent a birthdate for example). The RFC 3339 standard provides the formatYYYY-MM-DD
for representing dates. I am curious to hear your thoughts whether there is a place in the spec for aDate
scalar as well?