Skip to content
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

Add basic TimeZone support to Dates stdlib #51341

Open
simonbyrne opened this issue Sep 16, 2023 · 7 comments
Open

Add basic TimeZone support to Dates stdlib #51341

simonbyrne opened this issue Sep 16, 2023 · 7 comments
Labels
dates Dates, times, and the Dates stdlib module

Comments

@simonbyrne
Copy link
Contributor

simonbyrne commented Sep 16, 2023

Currently DateTime is completely time-zone unaware: this simplicity was intentional (as described by @quinnj in #49700 (comment)), with additional functionality pushed to TimeZones.jl.

The problem is that many packages skip time zone support altogether, or implement it in inconsistent ways: for example, now() returns a local DateTime by default, whereas TOML.jl treats all DateTimes as UTC.

Even packages which aren't in the stdlib are reluctant to use TimeZones.jl, resulting in bugs or less-than-useful information:

What I would like to propose is to add basic UTC and UTC + offset support into stdlib (basically functionality which doesn't require looking up a timezone database). This would be sufficient to fully support the TOML datetime and many other applications.

I was thinking something like the following

struct DateTimeZoned{TZ<:TimeZone} <: AbstractDateTime
    instant::UTInstant{Millisecond}
    zone::TZ
end

We already have UTC <: TimeZone defined, so we could also define

struct UTCOffset <: TimeZone
    offset::Millisecond # or could use Minute?
end

Similarly we could expand the datetime"" macro to support the Z (which would return a DateTimeZoned{UTC} and +00:00 suffixes (which would return a DateTimeZoned{UTCOffset}.

Like our current DateTime, we would continue to ignore leap seconds (as basically every other piece of software does).

This would fix the following issues:

@simonbyrne simonbyrne added the dates Dates, times, and the Dates stdlib module label Sep 16, 2023
@quinnj
Copy link
Member

quinnj commented Sep 16, 2023

I'd be in favor of this. cc: @omus

@simonbyrne
Copy link
Contributor Author

simonbyrne commented Sep 16, 2023

I would also be in favor of renaming UTInstant to POSIXInstant or something like that, since what we're doing doesn't really have any correspondence to UT in any way, but this is less of an issue.

(I guess POSIXInstant would not be correct either, since the epoch is in UTC, which DateTime avoids)

@giordano
Copy link
Contributor

struct UTCOffset <: TimeZone
    offset::Millisecond # or could use Minute?
end

There have been timezones with non-integer offsets in minutes in the past, for example: https://en.wikipedia.org/wiki/Moscow_Time#History. Milliseconds should be a safer choice

@tecosaur
Copy link
Contributor

tecosaur commented Feb 3, 2025

I wonder if there's some value in mentioning https://github.com/BurntSushi/jiff, which seems to take an approach rather in line with (what I'd hope at least) Julia stdlibs aim for:

The most important design goal of Jiff is to be a high level datetime library that makes it hard to do the wrong thing. Second to that is performance.

There are a number of interesting choices in the library, such of the use of nanoseconds not microseconds to represent instances, only bundling the timezone DB on windows and using /usr/share/zoneinfo / $TZDIR on Linux, and supporting eras (BCE, CE).

@omus
Copy link
Member

omus commented Feb 3, 2025

I'm not opposed to having this but it would be nice to avoid having a DateTimeZoned defined in Dates.jl and ZonedDateTime in TimeZones.jl. I think having both would lead to confusion.

Even packages which aren't in the stdlib are reluctant to use TimeZones.jl,

Do we know why these packages are reluctant to depend on TimeZones.jl? Since the creation of TZJData.jl we've switched to artifacts for tzdata information which eliminated processing done previously during package initialization. If there are other concerns we can possibly address those directly TimeZones.jl

There have been timezones with non-integer offsets in minutes in the past, for example: https://en.wikipedia.org/wiki/Moscow_Time#History. Milliseconds should be a safer choice

The initial offsets for most time zones in the IANA tz database include a offset with seconds. I've not seen anything with a higher resolution than seconds though.

@simonbyrne
Copy link
Contributor Author

@omus Honestly I think it's because TimeZones.jl is overkill: they don't need actual time zones, just UTC time.

Thinking this through a bit more, I think simply doing something like

struct DateTimeUTC <: AbstractDateTime
    instant::UTInstant{Millisecond}  # or UTCInstant?
    offset::Millisecond
end

might be sufficient.

@omus
Copy link
Member

omus commented Feb 26, 2025

I'd be more in favor of having the more limited scope of DateTimeUTC. Do you even need the offset in your proposed type? You could just do:

struct DateTimeUTC <: AbstractDateTime
    instant::UTInstant{Millisecond}  # or UTCInstant?
end

Effectively we would just be defining a type to be explicit that this datetime is in UTC. We would probably want to disallow conversion between DateTimeUTC and DateTime to avoid confusion when working with these types.

Honestly I think it's because TimeZones.jl is overkill: they don't need actual time zones, just UTC time.

Another solution we could consider is splitting out ZonedDateTime from TimeZones.jl and having it exist in a separate package which doesn't depend on TimeZones. This would support fixed UTC offsets and could perform basic parsing of string with the Z suffix. I suspect that the packages which are avoiding TimeZones.jl are just trying to avoid dependencies outside of the stdlibs though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dates Dates, times, and the Dates stdlib module
Projects
None yet
Development

No branches or pull requests

5 participants