Using EST as a shortcut isn’t a good idea, either - most software will “know what you mean” and use EST or EDT appropriately... except, both The USA and Canada have been toying with the idea of dropping daylight savings time, so it’s very possible at some point in the future that 6:00pm on July 1st will be EDT in America/New York, but EST in America/Montreal (or vice versa). This is already true for CST - Saskatchewan doesn’t use DST. And there have been times where one country or another changes the start date or end date of DST too, so there’s no reason to assume those will always be the same between Canada and the US.
So at/near the equator, in a place like Panama, you will get roughly 12 hours of daylight in both the December and June Solstices.
* https://www.timeanddate.com/sun/panama/panama
Whereas in the Edinburgh you go from having 7 hours of daylight in December to over 17 hours in June:
* https://www.timeanddate.com/sun/uk/edinburgh
So people want those 7 hours to be when it's most convenient for them.
The basic idea is that it's easier to convince everyone that is actually 5:00pm and time to leave work than it is to convince just your boss that you want to start work an hour earlier and leave and hour earlier.
This problem is then applied to politicians and other powerful people, who want to go golfing after work. If there's no DST, the sun will set "earlier" according to the clock, and you can't get in a full 18 holes.
So therefore, we change all the clocks so that powerful rich people can go golfing.
No other group of people sees any benefits to DST.
It aims to shift the usable daylight hours to correspond with human activity.
If you search HN you’ll find plenty on this topic.
India does not use timezones. Every business, school, office who has business hours, use something like Winter Timings Summer Timings. Schools & such use 14 Oct to 14 Apr as Winter, & other 6 months as summer. My school used to open at 6 in summers, & 7:30 or 8 in winters.
Here in US they keep the opening timings same throughout the year, but go through this DST shenanigans.
There's no possible way businesses are going to adjust their hours twice yearly to let employees get more sunshine, but DST does that effectively by ensuring official timekeeping gets moved about on them.
Yes, but you can better align the available light with things like commutes and school hours - so that people commute in light instead of the dark, for example.
However, I recall that farmers are very split on the issue when polled - it impacts on their work shifts as well.
Power. The sensation of raw power.
By and large, the best way to eliminate DST would be for one or more sufficiently powerful lawmakers or political executives to say: this is no longer benefiting the public at large, and we are going to stop!
These are the folks empowered to change the date on which DST transitions (at least stateside). These are also the same folks whose careers have been mostly defined by the deliberate and incremental accumulation of power into their own hands.
If you're wired for that kind of desire for power, the ability to tell the entire country: okay, I am changing time! It happens on this date! --must be simply _irresistible_. I mean: you're literally changing TIME. Hot shit! The entire population has to respond! You're changing TIME! Why give that up?
While I'm storytelling and presuming, I'll note that this needn't be a deliberate, conscious decision; I'm only suggesting that the people positioned to change this sort of thing are probably naturally wired to resist doing so, and may not even be aware of why themselves.
But agree that this is just a grab bag of confusing garbage.
[0] I suppose if CA does away with DST (or keeps it permanently), I will have to change...
https://stackoverflow.com/questions/4309030/difference-betwe...
Europeans turn back clocks for daylight saving, perhaps for last time. source: https://www.dw.com/en/europeans-turn-back-clocks-for-dayligh...
The EU's "Ban DST" is the same populist bullshit as Trumps "inject Windex to cure COVID". Based on nothing and ignorant at best.
And the cherry on top is, if you ask the EU if they want to receive a no strings attached gift of €10.000.000.000.000 or €11.000.000.000.000, it would still take them 20 years to decide. No way they will ever reach consensus on DST.
EST is always UTC-4 and EDT is always UTC-5. Both of these exist throughout the year. The only change happening in Spring/Autumn is that some places change which time zone they currently observe.
This also addresses the second problem that you outlined. As long as the query is properly specified (if you want information related to a location, use America/New York; if you want information related to a time zone, use the time zone), you can always get an unambiguous and correct answer.
Except you have those reversed. :)
Unfortunately not. Australia also used EST until recently. Now they've introduced AEST, but I'm sure there's systems out there using EST.
Individual states are toying with the idea as well [1], which presents a problem if one of the tzdata locations decides to change its rules. You're screwed no matter what you choose to do. :-(
1: https://www.syracuse.com/state/2020/11/state-senator-introdu...
I feel the standard interchange format for datetimes really should be 64 bit Unix timestamps. These are trivial to store in any database as a native type, can be compared using the fastest arithmetic instructions possible, and are a locale agnostic representation suitable for direct business logic comparisons.
Trying to carry timezone information around is a mistake. This is state that should be terminated and normalized at both ends, not passed through the system.
The only thing I would store pertaining to timezone is for user profile or server environment configuration. These would be settings in the application that are used to produce locale-specific UI and reports.
There are probably some other use cases I am not thinking of, but that is the extent of how we do it and we have a really complex app that has to serve customers who operate in multiple timezones at once.
No.
If a human says a recurring meeting happens at 9 AM Pacific time and the following week they are in daylight saving time, it'll still happen at 9 AM local time. Preserving intent is crucial in this case.
Time is something that developers get wrong more often than any other type. Your time data requirements change as your use case for the time changes.
From https://github.com/kstenerud/compact-time/blob/master/compac...
Aside from issues of synchronization, leap seconds, data container limitations and such, it's important to choose the correct kind of time to store, and the right kind depends on what the purpose of recording the time is.
There are three main kinds of time:
*Absolute Time*
Absolute time is a time that is fixed relative to UTC (or relative to an offset from UTC). It is not affected by daylight savings time, nor will it ever change if an area's time zone changes for political reasons. Absolute time is best recorded in the UTC time zone, and is mostly useful for events in the past (because the time zone is now fixed at the time of the event, so it probably no longer matters what specific time zone was in effect).
*Fixed Time*
Fixed time is a time that is fixed to a particular place, and that place has a time zone associated with it (but the time zone might change for political reasons in the future,for example with daylight savings). If the venue changes, only the time zone data needs to be updated. An example would be an appointment in London this coming October 12th at 10:30.
*Floating Time*
Floating (or local) time is always relative to the time zone of the observer. If you travel and change time zones, floating time changes zones with you. If you and another observer are in different time zones and observe the same floating time value, the absolute times you calculate will be different. An example would be your 8:00 morning workout.
*When to Use Each Kind*
Use whichever kind of time most succinctly and completely handles your time needs. Don't depend on time zone information as a proxy for a location; that's depending on a side effect, which is always brittle. Always store location information separately if it's important.
Examples:
Recording an event: Absolute
Log entries: Absolute
An appointment: Fixed
Your daily schedule: Floating
Deadlines: Usually fixed time, but possibly absolute time.
And fixed time I would call local time. Why call it fixed? Because it's tied to a location?
Several people have already replied pointing out that for scheduling events in the future, particularly recurring events, it's practically necessary to refer to time zones.
So I'll just mention the problem of leap seconds, which are announced six months in advance. If a one-second error could cause problems then probably you should use TAI rather than UTC. But you still need UTC for other purposes, so probably you need both and so you need to keep track of whether a particular timestamp is TAI or UTC.
You store your datetimes/instants as UTC, you store your "every day at 9 CST" rule separate from that.
Your rule table might have a column for a cron expression, and a column for the tz database name.
Meanwhile, your table for the meeting records has the time represented as a UTC timestamp.
UNIX timestamps are ambiguous.
ISO 8601 is perfectly good interchange format.
Besides the "meeting time" exception others have mentioned, you should be aware of timezones when grouping records into days/weeks/months/years/etc. The timezone affects where you "cut" the continuum into groups. Does Joe's sale count toward his January quota or February? This has all kinds of interesting questions: do you use the user's time zone? The local office timezone? The HQ timezone? UTC for everything? What if the user moves? Stack Overflow's "fanatic" badge just uses UTC: https://stackoverflow.com/help/badges/83/fanatic
Use UTC everywhere, then display in the user's timezone is a perfectly valid pattern...for specific use cases. Those use cases are very common, but many people over generalize, and assume that it can handle all cases.
I still don't understand the arguments about a future date requiring a timezone. UTC can 100% accurately represent a future date or event without any ambiguity. If a user, meeting or other aggregate has a culture/timezone preference, this is a completely separate business fact from the time.
All you need to read/remember is this, this applies everywhere not just with date.
Just use UTC for most things.
As with all things time, I'm no expert, and could be wrong about something. If you are, please correct me!
Easy example that I have to deal with semi-regularly since I live and work in Mountain Time: Arizona. Arizona is under Mountain Time, but does not observe Daylight Savings. So America/Phoenix would work fine (and America/Denver for the rest of the Mountain Time zone) but simply using MT would not.
To complicate matters even more is that the Navajo reservation (which is partially in Arizona) observes DST, but the Hopi Reservation (also in Arizona, but completely surrounded by the Navajo Reservation) does not.
One of the first surprising things you learn after launching a timezone conversion website https://news.ycombinator.com/item?id=1133613 is that one of the top feature requests is to display short timezone codes.
A few moons ago, that led me down a whole new rabbit hole of its own that is Golang's time zone parsing capabilities (https://github.com/golang/go/issues/9617), which, at least for Elastic's filebeat, seem to vary at runtime depending on whether or not you have a time zone database available...
Moral of the story: Please just conform to ISO-8601 everywhere.
https://codeofmatt.com/on-the-timing-of-time-zone-changes/
I think the right thing is to store times with the timezone the user wanted when they created the time. You can often use defaults or other UX niceties to streamline specifying TZ, but not always.
Also, if you'll want to unambiguously know the timestamp's exact point in time at some point (like for comparison with other dayetimes), you should save the offset from UTC alongside the actual datetime. Otherwise, around clock changes like "fall back" you cannot tell if you're seeing 2 AM for the first or second time.
This is the best I've come to trying to piece datetime storage together. If someone has better advice, I'd love to hear it.
For more of my theory on timezone handling and the sources I've used to help me think it through, see http://howicode.nateeag.com/dates-and-times.html .
Summary:
UT1 - noon is when the sun is above you, day has 86400 seconds (not SI seconds)
TAI - noon drifts away from when the sun is above you, day has 86400 SI seconds
UTC - noon is when the sun is above you (+/- 1 second), day has 86400+/-1 SI seconds
Difference UT1-TAI: continuously diverging
Difference UT1-UTC: continuously diverging up to less than +/-1 second, then discretely jumps back when it gets too big (leap seconds)
Difference TAI-UTC: increasing in discrete increments of +/-1 full second (leap seconds)
Yup. If you say CST do you mean China Standard Time or Central Standard Time? The answer will depend on where you live in the world. There are others that share the same abbreviation as well. But CST is the one that constantly causes trouble in daily life. Just say no.
Expected:
$ TZ=LOL_THIS_DOESNT_EXIST date Sat 10 Jul 2021 12:00:00 AM LOL
Actual:
$ TZ=LOL_THIS_DOESNT_EXIST date Wed Feb 10 17:02:02 UTC 2021
Otherwise I agree with the article. Have told so many co-workers that storing your dates in anything other than UTC will bite you in the ass later on. Converting it to the relevant time zone for display purposes is a trivial operation.
I bet storing an offset is far more pain, given that anyone in a DST area will have 2 offsets per year.
Offsets can be useful if one is attempting to record a historical incident, where the timezone had a particular-defined offset at the point in time the incident occurred (though for my money, I'd just convert that time to UTC on storage).
$ TZ=EDT gdate
Wed Feb 10 13:22:23 UTC 2021
$ gdate --version
date (GNU coreutils) 8.32
...
8.30 (shipped in debian buster) still has the problem.The BSD version of date shipped with MacOS 10.15 also does not seem to have this bug.
Testing with https://hub.docker.com/_/busybox, it seems like musl also has this problem. uclibc is not affected.
Are there any more examples of them causing issues to warrant being called "disastrously bad"? This post just seems to have one example of bad error handling when they the TZ env var is set incorrectly.
I'm genuinely interested if they actually are bad since they are used a lot.
It gets worse now that you have countries next to each other that are out of sync on daylight saving - America/Los Angeles doesn’t work for those south of the border anymore - but you won’t notice except two weeks a year.
Strangely I’ve noticed some systems give you WAY more cities than in the standard library - and I’m not sure why. Linode had way more options than just America/Chicago but didn’t have St Paul.
And trying to schedule things in advance across the daylight saving time difference is even more confusing.
At some point, the problem must've come up "if it's 5pm here in SFO, what time is it in MIA?", or some variation on that theme.
Someone decided that the best way to answer this was to write a function that took a date_time, then altered it to apply an offset between timezones. e.g. time_local_to_tz.
So you can could take a date_time in SFO, do time_local_to_tz (supplying Miami's TZ) and get back a date_time value that would to_string in SFO to show "the time in MIA". These functions made their way into a standard library and then to a lot of code.
The only problem is that the assumptions are literally all wrong. Adding the offset changes the actual point in time being addressed, which can change the timezone in effect in the current location, which results in the result skewing. This was compounded by some developers assuming that maybe they should convert their times to UTC before persisting them.
Of course, the usage of these functions is now embedded in a bunch of code no-one dares to touch, because it is full of hacks to "make it work" and quite possibly there is other code somewhere else (separated by a network connection, or a file, or persistence into a database) that is predicated on undoing those same set of hacks.
The app was for displaying time-series data. The data displayed was only generated during business hours. We usually wanted to view a span of a couple of weeks. Displaying it naively, with real time along the x-axis would mean that three-quarters of the display was blank, with only 40 of a week's 168 hours in use.
The obvious thing to do is to elide the blank bits, and just show the spans of time with data (with a little gap in between). But the charting library i was using didn't have the concept of a discontinuous or nonlinear x-axis.
So i wrote a class called TimeCompressor that would collect a set of time-series data, indexed by epoch timestamp, and rewrite the timestamps so that empty spans of time would be compressed. The earliest timestamp in the dataset stays the same, but later ones may be slid earlier in time to compress empty spans. The resulting indices are numbers which look mostly like epoch timestamps, and in some cases actually are epoch timestamps, but really aren't epoch timestamps.
This was all done in JavaScript, so there wasn't a convenient way to wrap the not-really-timestamp indices in a type to mark them as such. So, in this application, when there's a field called somethingTimestamp and it has a large integer that looks like a timestamp in it, sometimes it's a timestamp, and sometimes it isn't!
I am hoping this application will be retired before i ever need to work on it again.
Ideally the world should switch to an "earth calendar" where the year begins on the shortest day (currently Dec 21st for 90% of the population) and there are four yearly planet-wide holidays:
1. northern solstice
2. southern solstice
3. northward equinox
4. southward equinox
While we are at it, we could also do something more clever than months, weeks and the time system. 24/60/60 is a pain.
Unfortunately, .beat time didn’t catch on.
If a user provides a time of 11/7/2021 1:50 AM America/New_York, how does the library determine if it's a -5 or -4 offset given that's when daylight savings time ends? I believe that's the ambiguity GP is referring to.
I'm trying to align time across a few systems I work with. One provides a GMT time with an offset (clean and useful), another system reports timezones and local time, and yet another system has no idea when it moves between time zones, but reports time based on a single timezone consistently.
Not dealing with multiple timezones in the past, it reminds me of Tom Scott's video on handling time and timezones, summarized at the end as roughly "Go find someone who built a library for handling times, thank them profusely, use their open source code, give them credit, and never worry about it again."
> The mktime() function converts a broken-down time structure, expressed as local time, to calendar time representation. The function ignores the values supplied by the caller in the tm_wday and tm_yday fields. The value specified in the tm_isdst field informs mktime() whether or not daylight saving time (DST) is in effect for the time supplied in the tm structure: a positive value means DST is in effect; zero means that DST is not in effect; and a negative value means that mktime() should (use timezone information and system databases to) attempt to determine whether DST is in effect at the specified time.
So, not specified.
POSIX is no clearer about which choice it will make [1]:
> The mktime() function shall convert the broken-down time, expressed as local time, in the structure pointed to by timeptr, into a time since the Epoch value with the same encoding as that of the values returned by time(). The original values of the tm_wday and tm_yday components of the structure shall be ignored, and the original values of the other components shall not be restricted to the ranges described in <time.h>.
> A positive or 0 value for tm_isdst shall cause mktime() to presume initially that Daylight Savings Time, respectively, is or is not in effect for the specified time. A negative value for tm_isdst shall cause mktime() to attempt to determine whether Daylight Savings Time is in effect for the specified time.
> Local timezone information shall be set as though mktime() called tzset().
> The relationship between the tm structure (defined in the <time.h> header) and the time in seconds since the Epoch is that the result shall be as specified in the expression given in the definition of seconds since the Epoch (see XBD Seconds Since the Epoch) corrected for timezone and any seasonal time adjustments, where the names other than tm_yday in the structure and in the expression correspond, and the tm_yday value used in the expression is the day of the year from 0 to 365 inclusive, calculated from the other tm structure members specified in <time.h> (excluding tm_wday).
> Upon successful completion, the values of the tm_wday and tm_yday components of the structure shall be set appropriately, and the other components shall be set to represent the specified time since the Epoch, but with their values forced to the ranges indicated in the <time.h> entry; the final value of tm_mday shall not be set until tm_mon and tm_year are determined.
... but i think the final paragraph implies that the tm_isdst field in the input time should at least be set to indicate which choice was made!
Java is explicit [2]:
> In most cases, there is only one valid offset for a local date-time. In the case of an overlap, where clocks are set back, there are two valid offsets. This method uses the earlier offset typically corresponding to "summer".
[1] https://pubs.opengroup.org/onlinepubs/9699919799/functions/m...
[2] https://docs.oracle.com/en/java/javase/11/docs/api/java.base...
$ date && TZ=LOLS-3:03:03LOLD,J101,J202 date
Wed Feb 10 17:44:44 EST 2021
Thu Feb 11 01:47:47 LOLS 2021
(My timezone is LOL Standard Time (LOLS), UTC+03:03:03, with support for changing to LOL Daylight Time (LOLD) during daylight savings, entering LOLD on the 101st Julian day of the calendar, and leaving on the 202nd Julian day of the calendar, excluding February 29th even in leap years.)I did actually missed a meeting due to that. I was in small city in Montana, checked list of these timezones, but didn't know which one to choose. So I saw Phoenix has the same time as me, and set it at my device.
However, turned out that Montana actually uses America/Denver (which is Colorado) as their timezone. Is there a way to know that?
Just stay away from Arizona and American time zones are easy and what you did would work.
Arizona is special because it's in mountain time, it doesn't observer daylight saving time so half the year it has the same time as pacific time except for the Navajo Nation which does observe daylight saving time but the Hopi Nation which is entirely inside the Navajo Nation doesn't follow daylight saving.
edit: picture of the Arizona timezone situation https://en.wikipedia.org/wiki/Time_in_Arizona#/media/File:Ar...
Here's a fun one: are timezones a mathematical construct or a physical construct? By which I mean: is the core of the problem to get the math right or to account for the geography of the planet?
It's a trick question. Timezones are a political construct. If your software is using timezones, it needs to somehow(1) account for changes to law, internationally. Individual countries can choose, for example, to use or stop using daylight savings time. Some have even chosen to shift the longitudinal timezone they consider themselves to be in.
(1) practically speaking, relying on tzdata (https://en.wikipedia.org/wiki/Tz_database) is a great solution to this problem for most use cases... But you need to keep your copy of it updated, because laws change.
And another still: assuming that all of a state uses the same TZ. Quite a few do not! Arizona for instance has several tribal timezones which honor DST while the state does not. Nevada has a little sliver of mountain time. Michigan has four counties in central time. And so on.
This stuff is hard to get right. And it’s important. “Just use UTC” is often the naive solution but it’s not good enough for a variety of use cases.
As far as the unix utilities go, the behavior is non-intuitive for sure, but can probably never be changed without breaking massive amounts of existing systems. The behavior is also reasonable considering the system constraints at the time it was written. Consulting an ever changing tz database every time the command runs was not an option, and maybe isn't even today.
Why? An average person (read: non-developer) rarely needs to think about their timezone, save for when it changes. As a human, it seems relatively straightforward to intuitively determine whether that person is in DST or not.
If you were a UNIX machine (or a developer providing input to one such machine, I guess), it might be more appropriate to ask for a response in the Americas/Chicago format or something like UTC-0600, but it seems rather coarse to require that everyone adhere to your personal timezone standards when interacting with you.
Personally, I frequently schedule meetings with clients all over the US where their timezone isn't necessarily clear to me, so I usually just say something along the lines of "1045am CT," omitting the S/D in its entirety.
But you don't know if someone used a calculator and invoked actual PST during the summer.
> I usually just say something along the lines of "1045am CT," omitting the S/D in its entirety.
Good.
One clock for the world. If that meant you started work at 0900 UTC and finished at 1700 UTC then fine, but if you lived in a different part of the world your work day might be 0100-0900.
It'd definitely take a bit of getting used to, but as the world becomes more intertwined, timezones are a pain and constant source of confusion.
Well.. Brisbane is not Sydney time. half the year we're 1 hour offset. AEST is not AEDT.
And even Central Standard Time is ambiguous
https://www.zainrizvi.io/blog/falsehoods-programmers-believe...
Nice blog post.
I am in the habit of using "Country/City" on everything that is not UTC, so I never encountered this issue. But it's so good to know.
Why not just use one universal time? At least we would know what time to agree on when planing a call. If I already have to look up the time zone in India before I call, it wouldn't be any harder to look up when people in India go to work or have lunch.
While we are at it I think we should move to a decimal time system. 100 seconds in minute, 100 minutes in hour, and 10 hours in a day. Naturally the second would be a bit shorter; the new seconds would be .864 current seconds. Then meetings could be scheduled in tenths of an hour, 0.2 hrs or 0.5 hrs etc.
We'd have to give this new world wide system a name, so that old time wouldn't be confused with new ones. I suggest saying something like 5.00-T8T (which stands for Todd8 Time) perfect!
Afer fixing the time we can fix the calendar. See the Hanke–Henry Permanent Calendar at https://en.wikipedia.org/wiki/Hanke–Henry_Permanent_Calendar
In terms of EDT, LOL, etc: again, well explained in the tzset manpage. EST works only because it appears the timezone database has EST and again, GNU is being helpful and assuming you meant to add the prepended colon.
It seems to me that the author did not initially read the documentation they linked to (https://www.gnu.org/software/libc/manual/html_node/TZ-Variab...) and is now complaining in an annoying and entitled manner.
It truncated the name because of the underscores, but you can do `TZ=somerandomthing date` to see it just reports what you say it is.
In this specific case though, even those docs do not explain what happens if the value is "invalid"!
By the documentation "EST", "EDT" and "America/Los_Angeles" are not valid TZ environment variable values, as none of them matches any of the formats. offset doesn't seem to be optional, and within offset hours are not optional.
Ok, maybe it is too pedantic, a permissive implementation can interpret no offset as 0, right? But that's not what happens here. The implementation looks up the timezone by the provided name somewhere, and only when it doesn't find it it falls back to 0 as an offset.
This lookup behavior doesn't seem to be documented on that page. It's not described in the GNU date man page either even though it uses TZ='America/Los_Angeles' as an example.
If the file specification filespec is omitted, or its value cannot be interpreted, then Coordi‐
nated Universal Time (UTC) is used. If filespec is given, it specifies another tzfile(5)-format
file to read the timezone information from. If filespec does not begin with a '/', the file
specification is relative to the system timezone directory. If the colon is omitted each of the
above TZ formats will be tried.It's not "EST", it's EST5EDT because the string "EST" shows up in other time zone designations. Learn time zones, then come back.