SiegeLord / Tango-D2

A port of the Tango library to D2
http://siegelord.github.com/Tango-D2/
Other
90 stars 38 forks source link

Time module has no timezone / DST support #90

Closed dhasenan closed 8 years ago

dhasenan commented 8 years ago

This is work that I am willing to do. However, there are some open questions I have, and it's unclear to me whether Tango is intended to be the subject of ongoing new development or just in maintenance mode.

tango.time.* doesn't support timezones or DST. Also, it's unclear what TimeOfDay is supposed to represent. If TimeOfDay.hour is set to 3, for instance, does that mean "when the clock shows 3" or "3 hours into the day"? While this is usually the same, it's not always -- for instance, on 1 November where I live, the third hour of the day was 2am (as was the second), and in March there will be a day where the third hour of the day is 4am.

Without these two things, DateTime can only represent UTC times.

There's also a lot of complexity and annoyance with Calendar.

It looks a lot like the Java date/time library, and that's notoriously bad.

I'd like to write a replacement. Something that makes it convenient to use the Gregorian calendar and timezones, and certainly something that makes it convenient to format dates and parse them.

There is one essential problem I've been concerned with. When I have a datetime with a timezone, I can treat it as a point in time primarily, or I can treat it as a representation of what a person will see on a calendar and clock first and foremost.

The former approach means it's safe to work with daylight saving time, but it's harder to work with changes in timezones. The latter means it's tricky to work with daylight saving time, but it's trivial to handle timezone updates.

For instance: I set an appointment for 2020-11-01 12:00:00 in timezone America/Los_Angeles. With the point-in-time approach, this converts to Unix timestamp 1604260800. Next year, the US decides to do away with DST, leaving us on summer time all year long. I originally set the meeting for noon local time, which now corresponds to Unix timestamp 1604257200. So what does that mean? My appointment is now an hour off.

Alternatively, we could store the time as if someone in that timezone wrote down their current date and time and timezone. This makes timezone updates work as expected, but now we find it difficult to add a timespan to a datetime. If, for instance, your datetime says (2015, 11, 1, 2, "America/Los_Angeles") and you add an hour, it's ambiguous whether the result should have an hour of 2 or 3.

Probably the safest way would be to store both the point in time and the human-readable timestamp. The timestamp is primary; the point in time disambiguates for DST.

There are some other decisions such as when to read tz data and how to make up for Windows's terrible handling of timezone / DST changes. I'm seeing articles that say people saw Windows apps reporting the wrong times for past events after the US changed its DST start and end dates circa 2007, and the API seems to assume a timezone is two fixed UTC offsets with a simple recurrence for switching between the two. On Posix systems, we can just read the timezone db off disk, of course, and that includes proper history. We could import timezonedb and include it as static data on Windows, mark the date of import, and use that for any dates before the import date, while using Windows timezone info for stuff later than that...it's tough, and a second opinion would be helpful.

For Posix, creating a datetime will sometimes cause disk IO. That's unfortunate. However, it's difficult / impossible to have up-to-date timezone data otherwise without causing annoying maintenance issues. (There's a timezone update? Better recompile Tango and then relink and redeploy your application! ...no. But since Windows doesn't offer anything better...)

Anyway, the goal for the new modules is to make it easy to work with datetimes (skip Date without a time; skip TimeOfDay) and timezones correctly, assuming the idealized Gregorian calendar. That means correct time arithmetic. It means easy parsing and formatting. It means accurate serialization and deserialization. It means not exposing a type that represents a datetime without a timezone.

SiegeLord commented 8 years ago

There is no real intention behind this port these days. I personally don't make big contributions to it, but I do my best to merge other people's work. That said, there aren't many users of Tango. The only super active person I know of is @jacob-carlborg, but perhaps there are others. It does seem like your ideas might be have a better life elsewhere, but it's not like I would block them from being included or anything of that sort.

In terms of your ideas, I don't have much experience with date handling code. I appreciate the benefit of matching what is displayed on the clock, as that is ultimately what would make this code useful. I don't really see the ambiguity with the addition of 1 hour to your DST example, to me it seems that it should be unambiguously what is displayed on the clock if you waited for an hour.

jacob-carlborg commented 8 years ago

@dhasenan I have not read your whole post but I recommend looking at std.datetime in the standard library (Phobos) that could of use to you. I've not used it myself but I looks to be very comprehensive.

@SiegeLord How much do you maintain Tango these days? I know before that you at least made sure it worked with the latest compiler.

dhasenan commented 8 years ago

Acknowledged. My knowledge of Tango is mostly five years out of date. I'll focus on Phobos instead.

SiegeLord commented 8 years ago

I maintain it by merging people's fixes :P. Since I had no D code of my own, I wouldn't even get notified that something broke until somebody else tried it... now that I added an travis script (a very basic one unfortunately), at least it'll tell me and perhaps I could fix some trivial errors.