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 a method to the Offset trait to return DST info #1562

Open
pitdicker opened this issue Apr 7, 2024 · 5 comments
Open

Add a method to the Offset trait to return DST info #1562

pitdicker opened this issue Apr 7, 2024 · 5 comments

Comments

@pitdicker
Copy link
Collaborator

We have had multiple requests to provide a way to get DST information for a DateTime.

Not all offset types carry this information. Utc and FixedOffset rightfully only encode an offset from UTC. Also some APIs may not give the information. So the method should not just return true/false but three variants:

enum DaylightSaving {
    Standard,
    Saving(FixedOffset),
    Unknown,
}

During DST the time is usually +1 hour shifted relative to the standard offset for that time zone. But there exist other values, such as +0:30, +1:30, +2:00, and -1:00. I propose to return the extra offset in the Saving variant as a FixedOffset.

What should be the fallback if you want to create an offset for an API that only provides a boolean for the DST status?
Honestly TZif files, chrono-tz and the Widows API have the full information. As I understand from discussions around the IANA time zone database an API that only returns a boolean is usually broken in various ways already (like handling a negative DST offset). We can leave the question up to the implementation that wraps it. I don't think it should effect our API.

Adding this method is backward-compatible if we give it a default implementation that returns DaylightSaving::Unknown.

@djc
Copy link
Member

djc commented Apr 9, 2024

I would be inclined to make this method return just Option<FixedOffset>. This seems a lot simpler and it's not obvious to me what the benefit is for distinguishing between unknown and "standard" time. Can you link to the requests you've seen for this so we can get the full detail of the use cases (to the extent provided)?

@pitdicker
Copy link
Collaborator Author

pitdicker commented Apr 10, 2024

Oops, replied on the wrong issue. Copying here.

(Not a reply, just some things I'm thinking about.)

Summer and winter time

The concepts of 'daylight saving time', 'standard time', 'summer time' and 'winter time' are related but not the same.
The IANA time zone database mostly concerns itself with the 'standard time' within a time zone, and encodes any deviations of that as 'saving'.

What is called 'summer time' often matches 'daylight saving time', with 'winter time' being the standard time. But countries may just as well define their 'summer time' the be the 'standard time', in which case 'winter time' will be encoded as 'saving'. Then there are many time zones that don't make a distinction between either, or only made the distinction for a couple of years. And of course Utc, FixedOffset and possibly others have no way to tell.

There can be reasons other than the seasons to switch to/from the standard offset within a time zone. In the US during World War II there has been 'war time', with a three year long DST. Or summer time (to make optimal use of daylight) may temporary revert to standard time during ramadan (where you eat beyond daylight). Contries may also move away from DST, and declare their daylight saving time to last the whole year. At this point it becomes the 'standard time' and is encoded as such in the database.

From only the DST info with Standard, Saving and Unknown it is not possible to say anything about 'summer time' and 'winter time' that is always correct.

However in a TimeZone implementation there is enough info to tell. For example it is 'summer time' or 'winter time' if the time zone alternates between standard time and DST around this date and the period covers a good part of the summer or winter for the hemispere of that time zone. Whether it alternates is something you can't tell from the offset of a single date (unless we encode that info in the offset). And if summer is around july or january is also not hard to tell with the continents already giving a good basis (which is not difficult info but implementation-dependend).

Because users may expect 'daylight saving time' to be the same thing as 'summer time', we should consider this difference instead of only naively exposing the basic data.


The time zone database contains a treasure trove of documentation around DST weirdness. Before suggesting a definitive API I'd like to read all the documentation the database has around it. That seems doable.

Some parts from the database:

Greenland

  • The bill to move America/Nuuk from UTC-03 to UTC-02 passed.
  • The bill to stop observing DST did not (Greenland will stop observing DST when EU does).

Details on the implementation are here (section 6): https://ina.gl/dvd/EM%202022/pdf/media/2553529/pkt17_em2022_tidens_bestemmelse_bem_da.pdf
This is how the change will be implemented:

  1. The shift to DST in 2023 happens as normal.
  2. The shift from DST in 2023 happens as normal, but coincides with the shift to UTC-02 normaltime (people will not change their clocks here).
  3. After this, DST is still observed, but as -02/-01 instead of -03/-02.

Ireland

… Ireland's Standard Time (Amendment) Act, 1971 states that standard time in Ireland remains at UT +01 and is observed in summer, and that Greenwich mean time is observed in winter. That is, when Ireland amended the 1968 act that established UT +01 as Irish Standard Time, it left standard time unchanged and established GMT as a negative daylight saving time in winter. … See: http://www.irishstatutebook.ie/eli/1971/act/17/enacted/en/print

Czech Republic and Slovakia (Europe/Prague)

From 1947 to 1979 Czechoslovakia had a standard time and a winter time where the winter time differed by -1:00 hour from standard time.

Marocco

Marocco has a super complex story when it comes to DST. It has a summer time, to make more use of the available daylight, but switches back to standard time during the ramadan (to eat after dark). This caused four DST changes per year in 2012 to 2016. And in 2018 it switched its definition of standard time, causing the 'saving' time to have a -1:00 hour offset to the standard time.

Namibia

Namibia is going to change their time zone to what is now their DST: https://www.newera.com.na/2017/02/23/namibias-winter-time-might-be-repealed/
… We have made the assumption so far that they will change their time zone at the same time they would normally start DST, the first Sunday in September.

Before the change, summer and winter time were both standard time legally.
However in common parlance, winter time was considered to be DST. See, e.g.:
http://www.nbc.na/news/namibias-winter-time-could-be-scrapped.2706
https://zone.my.na/news/times-are-changing-in-namibia
https://www.newera.com.na/2017/02/23/namibias-winter-time-might-be-repealed/

Moscow

Russia observed DST until it switched to permanent 'summer time' all year long in 2011. In October 2014 it switched to permanent standard time.The time zone database does not encode a permanent 'summer time', but considers this a change to the standard time.

@pitdicker
Copy link
Collaborator Author

Can you link to the requests you've seen for this so we can get the full detail of the use cases (to the extent provided)?

👍 After searching for it again I can only find two... #235 and chronotope/chrono-tz#130. #10 (comment) and #120 are not clear.

I would be inclined to make this method return just Option<FixedOffset>. This seems a lot simpler and it's not obvious to me what the benefit is for distinguishing between unknown and "standard" time.

I like returning an Option but am not sure yet if we shouldn't even return more variants or another type.

The story for chrono seems similar to std::string, which not always has the simple methods of other languages in order to be correct with UTF-8. Our first concern should be to return info that allows code to be written correctly, including for less common time zones (such as summer or winter time outside the US and Europe).

Also I think it is good to have one method on a trait that returns all info that is available. Other methods can be added to the Offset trait with default implementation or to DateTime if we want to give a simpler result.

@pitdicker
Copy link
Collaborator Author

Correctness and precision are not exactly the same thing, and it feels to me like you're chasing a level of precision here the requirement for which might be extremely rare, and, as such, not a great fit for a general purpose library such as chrono.

😄. Sometimes I am thinking out loud in these issues, sorry. Please read this one more as exploring an idea than proposing a concrete plan.

If we add a method such as Offset::offset_from_standard it could return a simple Option<FixedOffset>. If it is the standard offset it will return a FixedOffset of zero, if it is 'saving' it returns the difference between the actual offset and the standard offset for the time zone, and None can represent the case where we don't know.

Essentially we would bring the functionality of the OffsetComponents trait from chrono-tz to chrono.

@djc
Copy link
Member

djc commented Apr 10, 2024

Essentially we would bring the functionality of the OffsetComponents trait from chrono-tz to chrono.

Sure, that seems reasonable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants