graphql-python/graphene

Provide a way to configure default timezone of DateTimes

davidroeca opened this issue · 3 comments

Is your feature request related to a problem? Please describe.

This feature is a direct predecessor of #590 - proposed UTC default timezone.

Describe the solution you'd like

A way to either:

  • Globally define the default server timezone (I'd always pick UTC)
  • Specify default timezone on a per-DateTime basis

Describe alternatives you've considered

Alternatives require client-side manipulation, or a custom graphene type to manipulate timezone-unaware values.

Additional context

Local Time (unqualified).

This is an issue that I've come back to and had to solve a few times.

While

I don't think graphene should be responsible for defining the default timezone for a datetime since it could misrepresent the actual timezone for the underlying value.

makes sense intuitively, from a practical perspective, timezone-unaware datetimes get misrepresented as the local time on the client's side.

e.g. if the server is in a different timezone from the user's browser and doesn't tack on a timezone, then the user's browser presumes the timezone to be its own. A solution in moment requires manipulation like so:

// moment.utc handles the case where datetimes don't have tz info, and we
// should assume those datetimes are in UTC rather than EDT, etc. This is
// actually a server issue, and the iso strings should be returning `Z` at
// the end but are not https://github.com/graphql-python/graphene/issues/590
const dateLocal = moment.utc(serverDateString).local()

But that is a work-around, and fixing the server would be more important.

I think UTC is a sensible default from a server perspective because there is bound to be a client in another timezone. It would at least be nice to make this easier to do, e.g. some way to specify a server-default timezone (for backwards-compatibility, could be None).

I agree with the comment on #590 that it is not Graphene's responsibility to define a default timezone for datetime values.

While I understand the potential issues that can arise from handling timezone-unaware datetimes, it is ultimately the responsibility of the developer to ensure that timezone aware datetimes are properly resolved for any DateTime types. Additionally, if the datetime value is not timezone aware, we cannot assume that it is in UTC.

Defining a default server timezone could potentially misrepresent the actual timezone for the underlying value, and as stated in issue #590, UTC should not be the default timezone. It is best to leave the responsibility of handling timezone-aware datetimes to the developer and not the framework.

The DateTime Scalar uses datetime.isoformat internally to convert datetime objects into ISO8601-compliant strings. This function includes an UTC-Offset if datetime.tzinfo is specified on the datetime object. Is there any reason why you can't set tzinfo yourself? You could easily extend the existing DateTime scalar, too.

Other than that, I agree with the points stated in #590. DateTime time zone settings should be an issue solved in userland.

Is there any reason why you can't set tzinfo yourself?

If it's coming from a database that doesn't store timezone info and assumes UTC.

You could easily extend the existing DateTime scalar, too.

Yes this is a work-around that needs to be handled on a case by case basis when it's discovered.
When using tools like graphene-sqlalchemy, the queries are auto-generated via this code, relying on graphene.DateTime.

Defining a default server timezone could potentially misrepresent the actual timezone for the underlying value, and as stated in issue #590, UTC should not be the default timezone.

That's true. However, the following assumptions are required for the existing timezone-unaware DateTime object not to be misrepresented:

  • the client sends the datetime without tzinfo to the server and expects the server to send back that datetime as-is
  • the client doesn't expect clients in other timezones to interact with it

If either of these assumptions turn out not to be true, then either the data the client saves won't be the same as what they get back, or the meaning of the datetime will be different for clients across different timezones (they'll both see e.g. 9pm in their respective timezones).

I've been digging further into this. I think this is a broader issue with some database implementations, in particular MySQL <-> SQLAlchemy, which in turn leads to problems resolving graphene.DateTime through graphene-sqlalchemy.

While still I think the current use case is a problem, I agree that graphene is not necessarily the place to resolve the issue, and this problem is more relevant at the sqlalchemy/graphene-sqlalchemy level.