Trivia questions, easily answered by programmers who appreciate the subtleties of time math:
1. If someone leaves Vancouver at 1 am and arrives in Seattle at 4 am on the same day, and you know the distance they travelled is 240 km, what was their average rate of speed? (Correct answer: 120 km/h, 80 km/h, or 60 km/h, depending on what day it is. UTC storage helps here.)
2. If it's noon in Vancouver, what time is it in London, England? (Correct answer: 7 pm, 8 pm, or 9 pm, depending on what day it is. Knowledge of regional DST schedule differences helps here.)
It's my experience that when the programmers get date math correct, they may still find themselves fielding "bug" reports from enterprise customers who should understand the concept but don't (particularly if their business is billing or rate calculation -- think of short term billing for hourly parking or CPU hours as an example).
3. How many simultaneous "days" are active at any given time on Earth? (3; 11pm Wednesday on Baker Island is 11am Thursday in London and 1am Friday in Kiribati)
It is a good video. The good thing about using a library like Kalends is that it takes into account everything he mentions about different timezones into account. Just tell it the time, date, and timezone name.
Just be careful about generalizing too much and assuming things such as: "this time will exist again tomorrow". Or "next month also has a 31st day". Or "DST is always a 3600 second difference from standard time".
In my experience, the simplest way to program with times and dates is nearly always to convert to Unix epoch as early as you can in the process. Do all processing in Epoch, then convert back to something readable by humans at the last possible moment. This approach won't work in all circumstances, but it should be the standard approach unless there's a compelling reason not to.
Disagree. Use a date/time library and datatypes. Don't use integers, unix timestamps, or any other naive representation of time.
As with cryptography, don't attempt to write your own date/time code. You will get it wrong. Use the datatypes and library functions in your language or database.
Hi, I'm the author of the blog post and the library used in the examples.
For many operations the Kalends library actually converts to UTC (and UTC is almost the same as epoch). For instance to calculate the amount of seconds between two datetimes.
Your advice might work in a lot of cases, but if you have a good datetime library you should not need to IMO. But I am sorry to say that I do not think most datetime libraries are very good when it comes to timezones.
You don't have to manually say: oh this datetime is not UTC, I better convert it as soon as possible. If you need to save a future datatime which is not UTC, it is actually error prone to convert to UTC.
What Kalends does instead is to have a struct with an unambiguous, validated datetime and the timezone along with it.
That way, if for instance you are dealing with a datetime entered by a user, you have the actual datetime entered, but you still have all information you need to convert to UTC.
>If you need to save a future datatime which is not UTC, [...] a struct with an unambiguous, validated datetime and the timezone along with it.
It's less ambiguous but it's not 100% unambiguous because future policies of Daylight Saving Time and Time Zone / Time offset boundaries can be changed by governments.
Even if the struct had extra fields for flags such as "obey future DST changes" or "ignore present TZ if different from historic TZ at time of data entry", it's still ambiguous if geographic coordinates are not embedded within the struct. Then again, there's probably some more edge cases even with latitude/longitude coordinates. (E.g. should the future time be interpreted at lat/long of where he data-entered the datetime, or the lat/long of where he later experiences the datetime?!)
Dates specifying future events are very tricky++. Unless, it's a future date for something celestial such as a solar eclipse; in such cases, a future date as UTC is unambiguous.
++Because we all conflate concepts of "socially-constructed future datetime as shown on a wall clock" and "scientific future datetime". We stuff both concepts into the same data structures. Nevertheless, we write software that makes educated guesses about the user intentions for "future dates" and it works for 99% of the typical use cases. (e.g. "send smartphone notification for 12:30 lunch with Bob next week.)
Right, it is unambiguous for the current rules and zone. Usually if the rules change, you want to do the calculation again. I made a library for persisting future DateTimes to a database. Whenever a DateTime is loaded from the database, the calculation is done again. A blog post about it can be found at http://www.creativedeletion.com/2015/03/19/persisting_future...
If the "borders of the timezones" change, that does not make it unambiguous, because the struct is defined as belong to a timezone name, not a specific geographical location.
What I find missing from most, if not all, date/time libraries is a three-arg timezone conversion function (i.e. one that is pure and doesn't rely on the current time or locale). Most timezone conversions take a zoned date and time and convert it to a different timezone. But it matters when/where you're doing the conversion for the reasons you're discussing. If you also supply a UTC timestamp indicating when the conversion should take place (note, not a zoned date and time, since the conversion to the universal timeline can be affected by DST changes), that conversion can be consistent no matter when/where the function runs.
I find this approach to be cleaner than saving wall time since it allows you to keep uniform times on the server and simplify server-side logic that acts on those times in bulk.
>If the "borders of the timezones" change, that does not make it unambiguous, because the struct is defined as belong to a timezone name, not a specific geographical location.
The "TZ name" designation can change for a location so even if you store it in the struct, it's still ambiguous. It's not a common occurrence but it has happened before. It is impossible to store a 100% unambiguous socially-constructed future datetime that works for all edge cases.
To clarify, I'm not saying your datetime library is "incorrect" or needs to change. I'm just pointing out that your guarantee about it recording an "unambiguous future date" is not possible to achieve for all edge cases.
To use an Epoch you have to convert it into a timezone aware date (as you stated, as late as possible). Now that could be UTC but more likley it will be a timeZone that observes a daylight savings time.
Consider the epoch of 0, 1st of Jan 1970 or what ever it is. Well that's correct in GMT but if you are in NYC what time is it, how about Singapore, Australia, Huston etc...
I think it's best to make an explicit, type-level distinction between these things. JodaTime does this: you can have an Instant (which represents a point in time) or a DateTime (a human-readable date/time with a timezone), and if you try to pass one where the other is needed then you get a compile error.
I agree on the point of always be converting, but I'll settle with UTC. IMHO if you have a non-utc time one if two things should happen:
A.) Convert it to Utc.
B.) Show it to someone.
Got some 'splain'n to do if I catch non-utc manipulation or comparison going on in my code bases. And heaven help you should you stick a non-utc time into the database.
These are all good points and I have thought about it a lot.. It seems that all these issues arise from people wanting to schedule or track a future date that is itself tentative and ambiguous; at the mercy of policy changes.
Ignoring the case where you want to allow a user to track some tentative future date that can resolve to different absolute times there is another truth there: You recorded a future absolute time which now maps to a different local time due to your government mucking about. What about the people in Hamburg who were supposed to join the meeting but missed it because the absolute time shifted?
For usability sake I do absolutely see where you are coming from and the library is surely nice. But I'll stick with storing and mathing UTC unless I absolutely need to start taking these scheduling issues into account :)
I'm not sure I understand the point of saving the offset:
"To avoid ambigiuty we also save a third piece of data: the UTC offset. Note that the UTC offset is only there for the rare cases when the timezone does not change, but when there is an ambiguity we know about at scheduling time - that will usually be when the timezone goes off of DST and a range of time (usually an hour) happens twice in autumn when clocks are set back. In this example though this third piece of data is not used for anything."
This doesn't make sense to me? Great read otherwise. I hadn't considered this edge case!
The reason the offset is changed is ambigous datetimes that occur when going off of DST.
Let us say a user enters a datetime in the autumn. It happens to be a few minutes after the clocks are set back an hour. So the time is ambiguous. Which datetime exactly does the user want? The one before or after the clocks are set back? We show him a dialog and he chooses one. To differentiate we use the standard offset which is usally 0 or 3600 seconds.
Great, now we save it to the database as just wall time and timezone name and load it again. How do we know if it is 02:05 before the clocks are set back or 02:05 after the clocks are set back? We don't, unless we saved the UTC offset. But if we save the offset we know exactly which one it is.
But we don't want to use the offset we calculated from the beginning. That would get us the same error as if saving just the UTC time. So we only use the offset if we absolutely have to. This is what Kalecto does when loading a saved datetime from the library: we do the calculation based on the saved "wall time" and the timezone name. If that wall time is ambiguous we use the UTC offset. If there were no changes to the rules for that timezone - no problems.
Now, if we have a combination of the timezone rules changing and the saved datetime being ambiguous, the entered choice is no longer valid. We have to ask the user again or report an error.
Why do you prefer UTC? I feel storing plain unix times is simplest since there's no time zone information at all. And there's no possibility of forgetting a conversion, since (with most languages/libraries) different types are used for plain unix times vs. local times.
Just to be make sure we're talking about the same thing, by "plain unix time" I mean something like java.time.Instant, and by "UTC time" I mean something like java.time.ZonedDateTime with zone == UTC.
With ZonedDateTime, there's obviously a time zone field. We can have a convention of always setting it to UTC, but that introduces a possible source of bugs. We might call ZonedDateTime.now() and forget to pass an explicit zone. Especially if the author is a new contributor who hasn't been told about our convention.
Or we might use a library which produces ZonedDateTimes with the system's default zone. Then we have to canonicalize them at some point, and be very careful not to rely on the local date/time info prior to canonicalization.
I'd rather just use a type like Instant which has no time zone field, so that there's no need for any time zone convention.
Further, we might need to serialize a timestamp using a non-UTC timezone, say CST which is common in payments systems. If we're using UTC times, we might forget to convert from UTC to CST. If we're using a plain unix time, we're forced to specify a time zone when serializing, so it's harder to make a mistake.
This works brilliantly until you discover that the Unix epoch is ambiguous around leap seconds. Good luck sorting epoch-stamped events around leap seconds!
Try living in a time zone that is a half-hour deviation from standard time (Newfoundland & Labrador). When I first got an iPod my time zone simply wasn't supported by the software: https://discussions.apple.com/thread/179539
It would yield GMT +0h 19m 36s to the above location. I assume it was tied to a more precise point inside Amsterdam which would give you the 32.13 seconds.
Every town used to have their own local time based on the sun being at zenith at local noon. For example, a place like Oxford would be a few minutes behind London.
With the advent of railways, it became necessary to standardize things a bit. You can imagine the difficulty if each town a train stopped in had its own timezone!
We had software choke on a birth date once. For some reason these were sent in milliseconds, and that particular instance, midnight July 1st, 1937 didn't exist for this particular locale. At that time, the time was changed to a different meridian, and the clock was moved forward a few seconds.
In the 1940s, the nazis set all of occupied Europe to Berlin time, and it stuck. Before that time, Europe had a large number of time zones.
Living in germany I often times have to raise eyebrows at the basic assumptions american coders often have with regards to encoding, timezone awareness and other common defaults.
An american friend with french heritage noticed happily after moving to germany that the accent de gue on his last name was finally printed correctly on his mail and packages.
Actually I (as a Dane) feel that we are all fortunate because the US is in multiple timezones. Had one of the small single-timezone countries headed the IT revolution, we would surely have much greater problems, similar to the way ascii still lives on in systems where it clearly shouldn't.
All apps I'm building now has a US-audience which means that they have to be timezone aware per default as opposed to apps with a danish audience where I didn't have to be concerned about timezones. The truth is, timezones are a pain.
Lets not get carried away - everyone in Germany misspells my Swedish first name.
(Because I use a spelling that is not used in Germany everyone here "corrects" my name, even when I enter myself it on websites, etc.)
My French friend Stéphane (male) had a lot of trouble in the US. A very large number of sites and services don't let you enter the accent. Many places that had any kind of the human in the loop would also "correct" his gender to female and name to Stephanie.
Well that answers the question I've been asking people for years: why do people keep using PST when everyone in the world understands UTC+/-X but nobody has a timezone table in their heads? Well, timezones change (using summertime or not changes the most).
Especially when, for most of the year, even the US west coast doesn't use PST (they use PDT).
You may think I'm being pedantic, but most naive timezone conversion tools won't pick up this error for you, if you ask them to convert "1PM in PST to my local time". I once ended up on a conference call at the right time by myself because the other party assumed that London time was the same as UTC (it's not - they were in Daylight Saving Time, so they were an hour ahead).
I was also thinking the same thing, I have to Google this kind of things all the time, acronyms like this are absolutely not useful at all to determine the exact time things are going to run.
Time is huge. You cannot get it right in all cases. You can only get it right for your particular case. If you try to get it right for all cases, you waste resources on something that mostly doesn't matter, and dwarf your other resources.
Time is not just calendar apps, or cron. Consider relative dates in historical studies that span past, present and future.
Study the fuck out of your use case, get it right, don't worry about others' opinions and don't think that your solution applies generally to most other use cases.
Also, among the many resources for general and specific solutions to time problems is "Calendrical Calculations," by Dershowitz and Reingold. I found it randomly, bought it on a lark, and hope to $DEITY I never haver to care about time for anything critical.
I find most people doen't understand the difference between timezone and time offset.
I reciently had a huge issue trying to explain to people why we couldn't (easily) show the offset next to the city on a date time input, because we didn't have a native library to do it. They couldn't grasp that a date in the future could have a different offset for the same city and that they didn't all change at the same time.
If anyone is using JS checkout moment.js and also be aware that date objects in most client side runtimes are in the users timezone by default, and often doen't let you change the offset.
I'm pretty sure we had a big discussion on this a couple of months ago, but I cannot find the link.
Don't forget that for a lot of applications your users don't care about time zones. "I have a meeting every Monday morning at 10:00AM and some folks from around the world call in". Its up the the programmer to figure that out for all involved.
This was our topic from our local dev meetup last month. We have a video of it here: https://www.youtube.com/watch?v=ZQAELeiY68E. Interesting discussion of weird time bugs too.
Even when using a library that supports timezones (and DST), handling them is still a pain, especially if one has to deal with timezone aware and floating datetimes at the same time.
Its not just your code that needs timezone awareness, users are all shockingly bad at understanding timezones. Daylight savings in particular needs to die.
The hardest I have noticed is to make them understand that it is not only the time, but also the date that change.
So when discussing whole timestamp or time - everybody is somewhat aware there is going to be timezone involved.
Good luck however, if you need to ask the question: "Is the instruction date (yyyy-mm-dd) in the Counterparty (Sidney), Party (London) or System timezone (Brussels) ?"
I think a more considered way to say that is it's a UX challange.
You have to think about what the user want's to enter and what they want to see. It's especially hard if they are doing something like booking a flight, or car hire in another country, how do you know if they are thinking about local time or destination time?
1. If someone leaves Vancouver at 1 am and arrives in Seattle at 4 am on the same day, and you know the distance they travelled is 240 km, what was their average rate of speed? (Correct answer: 120 km/h, 80 km/h, or 60 km/h, depending on what day it is. UTC storage helps here.)
2. If it's noon in Vancouver, what time is it in London, England? (Correct answer: 7 pm, 8 pm, or 9 pm, depending on what day it is. Knowledge of regional DST schedule differences helps here.)
It's my experience that when the programmers get date math correct, they may still find themselves fielding "bug" reports from enterprise customers who should understand the concept but don't (particularly if their business is billing or rate calculation -- think of short term billing for hourly parking or CPU hours as an example).