If SF decided to drop DST, but the rest of the state didn't[0], then America/San_Francisco would be created to handle the changes.
This is why you can't accurately record physical appointments by date, time, and timezone. You have to record it as date, time, and physical location, and then the time zone can "float", based on the location and rules in the tzdb, until the appointment happens.
[0] Assuming this were made legal, which is pretty unlikely.
What I'm saying is that we cannot reliably store a future local time such as "13:00 on the 12th Sept 2025 Europe/London" as an instant in time.
Recalling Einstein and that such a thing as global time reference is fundamentally impossible, you're nitpicking while being technically incorrect.
[0]: but please keep defaulting to it in code unless you really know why lol
It all boils down to picking the appropriate reference frame, which varies by context. I believe your point should be that there is no single universally applicable reference frame for mapping all future events to future cultural time (and/or that in any case it's not UTC).
No, a future datetime expressed in this string format does not represent a specific instant in time. If you had multiple datetime values from different timezones in this representation, you wouldn't be able to sort them so that earlier ones come before later ones. If they were instants in time, you would be able to do that.
"13:00 December 25 2025 Europe/London" is local time but its Unix timestamp is an estimate depending on how the tzdata database looks right now.
"13:00 December 25 2025 +0100" is also local time but it is immutable.
Using the latter can only be done reliably for present and past (but it conveniently avoids looking up the offset later). All future times must use the former to be stable otherwise you should probably be using UTC.
That's irrelevant.
Besides, you could, assuming you have a timezone db on the side.
> If they were instants in time, you would be able to do that.
How do you synchronize with and translate to timezones in Andromeda?
It is proof that your format does not represent instants in time because instants in time can be sorted across timezones.
>Besides, you could, assuming you have a timezone db on the side.
No, because you don't have future versions of the timezone database.
It would be highly unusual and misleading to call something a timestamp unless it is a point in time. In Postgres for instance, the timestamp with timezone type represents an instant in time.
This data type cannot be used to store things like reminders for future appointments. It's not rare at all.
Something that often trips people up is that they think timestamptz stores a timestamp plus a time zone (probably because of its unfortunate name). It does not; it always stores a Unix epoch without an extra time zone, converting any zoned timestamp that it is passed.
Taking your example of an appointment, a nominal (date)time would be appropriate if the meeting were to take place at a particular local time but in an as-yet unspecified geographical location, which will be specified later. The form of the appointment would be "we will meet at 13:00 according to the local convention in the place where the meeting actually happens, which is yet to be determined". Here, a nominal time would be appropriate, but note that it would need to be paired with some geographical information prior to the appointment taking place in order to identify a point in time, allowing the meeting to go ahead.
The above is a very unusual situation, though. It's far more likely that the meeting will be either in a location known up front or in no particular location (eg. if it's a video call with participants in multiple countries).
In the first case, the correct thing is to include the geographical timezone of the location where the meeting will take place. For example, if the meeting is in London the timezone would be Europe/London. You raise the concern that the local convention could change, eg. daylight saving time could be abolished, but that isn't an issue. The "whatever the convention is in operation in London at that time" part is captured in the use of Europe/London as the timezone, and there would be no need to update the (date)time if the convention changes. The (date)time identifies an instant in time as long as the convention doesn't change, but if the convention does change it automatically reflects it.
In the second case we need to define an instant in time so that people know when to attend the meeting. This could be done with a count of milliseconds from an agreed reference instant, but that's not very user friendly. The correct thing to use here is a (date)time with a defined timezone. If there really is no favoured location UTC would be the obvious choice, but any preferred timezone could be used as long as it's indicated in the (date)time so that the specific instant can be resolved. You might want to avoid using a zone like "Europe/London" whose convention could potentially change, although if you did use it the instant at which to to connect would still be well defined at the time of the meeting.
You rightly point out that nominal datetimes don't define instants in time, but that's why you should avoid them. Most use cases should specify a point in time, at least up to local convention in a specific location. Genuine use cases for nominal (date)times are rare. In the vast majority of cases where they are used a timezone really should have been specified. This mistake is extremely common, and it doesn't remotely surprise me if some programmers at Apple have made it.
A brief note on "local" times. These aren't the same thing as nominal times. A local time has an implicit timezone that is the local one according to the current locale. Local (date)times therefore do specify particular instants in time. One of the biggest mistakes people make is to write out local (date)times as nominal (date)times to stores that can be read by code running with different locales. This causes many problems. If you write out a local (date)time include the current time zone!
I ask you please to learn from the above. I know it's hard to prevent comment exchanges turning into arguments, but I'm not trying to win points here. I've taken a chunk of my Sunday morning to explain something I don't find terribly exciting in the hope that the knowledge will benefit anyone who reads it. I really hate being in a situation where I have a timestamp from a log or db or on the wire or something and whoever put it there didn't think to include the information needed to interpret it correctly. It happens to me distressingly often at work. Let's all do better.
Edit: Worth noting that ISO 8601 doesn't allow timezones like Europe/London. That's disappointing but doesn't relieve you of the duty to include the timezone information when persisting (date)times. It just makes it slightly more awkward. Good date/time libraries do support these zones.
Future physical events, such as an appointment at a physical location, should be stored as unzoned time plus a location (such as an address), NOT with a named time zone.
This is because physical locations can change named time zones due to political reasons (this has happened many times already).
Storing an appointment time with “Europe/London” only works if your appointment is actually in London and not some other British city (and even that assumes that London never gets divided in the future).
If I say meet me in person at 10am March 5th, 2030 in Dnipro, Ukraine, that's specific to a location, not Europe/Kyiv.
Why? Because perhaps in 2030 Russia has taken over Dnipro and moved it from Europe/Kyiv to Europe/Moscow.
Our meeting time has obviously not changed, but its exact instant on the universal timeline has changed.
This is super important to get right and you are spreading incorrect information that, if followed, will lead to bugs.
What I'm explaining is that it's usually wrong to store a nominal (date)time that can't be resolved to an instant in time without assuming extra information that isn't captured.
If fauigerzigerk isn't arguing in favour of doing that, and I've misunderstood the prior discussion, then great. The point should be made anyway, because people doing that is by far the biggest cause of time-related software issues in my extensive experience.
fauigerzigerk is saying that this, among with others, is the use case for what they are calling “local time,” what you are calling “nominal time,” what Postgres calls “timestamp without time zone,” and what the JS Temporal API calls “ PlainDateTime.”
In my experience engineers not understanding this key point, and believing that zoned time should be used for everything, is its own cause of issues and confusion.
The most recent time this happened was March of this year, with Chile's Aysén Region dropping DST and moving to the newly created America/Coyhaique.
https://data.iana.org/time-zones/tzdb/NEWS
I used to manage a large application for scheduling shifts at warehouses in many different locations, and storing future events as local timestamps and lazily converting them just before calculations into their location’s zoned time was the only way I could stay sane.
Even for people who live in Aysén, it will probably only happen once in their lives, and the only impact will be a few appointments getting messed up. Is having to fix a few calendar entries once in your life really “super important” to avoid?
Dealing with and debugging time zones is already such a confusing mess that I find that anything that makes your application more correct with regards to time zones is worth it. The important thing though is knowing, and then you can make an informed decision on how may shortcuts you want to take with time zones.
If you’re writing software that’s only designed to be used in a small region or by just a few people, then sure, it’s probably not super important.
If you’re writing software that’s used all over the map in places and time zones you can’t predict, well, it helps me sleep better at night.
If they were stored as instants, and then if a location moved time zones or stopped using DST in the summer, the event’s stored time relative to the expected local time would incorrectly shift.
My point is very simple. We cannot store all date/time values as a point in time (instant). There are important use cases where the exact point in time cannot (yet) be determined when we store the date/time value.
I disagree. Storing appointment reminders is not rare. Storing the datetime of future social events or deadlines is not rare.
I'm not interested in an argument either. Just use the correct representation for the use case at hand. It doesn't matter how rare or not rare it is in your work.
It is absolutely a fact that for the use cases you describe, you do eventually have to turn it into an instant in time. Otherwise you don't know when to issue appointment reminders and so on.
Because a location changing its IANA time zone identifier is rare, then capturing the "nominal" datetime, plus the offset and the time zone identifier is usually sufficient. That information can be encoded using RFC 9557. The offset can be used as a checksum of sorts to avoid silent bugs in cases where the location changes its DST rules. It does not help with your Ukraine example.
However, the only way to make your Ukraine example work is to necessarily have a way of mapping a physical location to an IANA time zone identifier. The IANA tzdb does not provide that on its own. This may be a fair bit of additional work that is not worth doing.
It's definitely wrong to just store an instant in time with a time zone though. You want the local datetime, the offset and the time zone at minimum. I'm surprised nobody in this thread has brought up RFC 9557.
It would be wonderful if Jiff supported coordinates-to-tz lookups out of the box :)
[0]: https://github.com/evansiroky/timezone-boundary-builder/rele...
[1]: https://github.com/evansiroky/timezone-boundary-builder#look...
[2]: https://www.crunchydata.com/blog/timezone-transformation-usi...
Finally, the database you linked doesn't appear to track historical data, unlike the tzdb. So if Ukraine reacquired territory, you'd end up with a wrong answer if looking at appointments scheduled in the past.
Further, I believe the historical data is meant to be handled by the named time zone, so Russia moving Dnipro to MSK would create a new time zone, call it Europe/Dnipro, then Ukraine reacquiring the territory and moving it back to EET would keep (or further split) Europe/Dnipro, and the historical changes of Dnipro would be handled by tzdb.
So even if you did store past events with a local time plus a location (which you should not do), I don't think Ukraine reacquiring the territory would cause problems, although we're really stretching my knowledge of IANA named zones and I could certainly be wrong.
Appointments become past events. Sounds like an operational nightmare to convert all of them right as they become past events.
And you absolutely want the time zone (and offset) if you want to show past event as a local time for where that event was held. You don't need the location because you know what time zone rules governed that location at that point in time in the past. It won't change.
Please consider that I phrased my comment in engineering terms. I already acknowledged that you want a physical location for the best results in all cases, as you have pointed out in this thread. But I also was careful to contextualize it in engineering terms: storing that information comes with extra engineering costs over just storing an RFC 9557 string. Sometimes those costs are worth it, but certainly not for every use case.
> Further, I believe the historical data is meant to be handled by the named time zone, so Russia moving Dnipro to MSK would create a new time zone, call it Europe/Dnipro, then Ukraine reacquiring the territory and moving it back to EET would keep (or further split) Europe/Dnipro, and the historical changes of Dnipro would be handled by tzdb.
I can believe that this is what would happen.
That is fair. In some models there's a natural separation between a scheduled-at time and a happened-at time (e.g., in one I worked on scheduled_events was a separate table from past_events), but I accept that's certainly not all, or even most. I shouldn't have made such a blanket statement. I do believe the statement is good advice in cases where your data does not mix both future and past times.
> Sometimes those costs are worth it, but certainly not for every use case.
This is also fair. My experience with time zones has been the more correct I can make my time models, the better I sleep at night, but of course you're right engineering involves tradeoffs. I think it's important to at least know the most correct way so that you are making educated decisions in your tradeoffs.
Also, FWIW I'm not the person you originally replied to, although the Ukraine example was mine.
If the latter, we don't disagree. There's more than one way to do it and plenty of use cases with special requirements (though IANA timezones are sufficient for most purposes). If the former, we profoundly disagree and if you are a professional programmer working in a field that makes significant use of times across multiple regions you will create misery for your colleagues until you change your approach.
But you will at least be far from alone in doing so...
Yes, but we cannot know which timezone that will be or how it will be defined and therefore we cannot store this appointment as a point in time.
This is what we're talking about, right? Can we store all datetimes as points in time or not? I'm convinced that we cannot always do that because there are datetime semantics that cannot be expressed in that way.
[Edit]
>You wouldn't use a datetime for an alarm clock, just a time
You should tell Apple that. They somehow managed to get this wrong. And I suspect the reason may be that many developers really really want all (date)time specifications to be points in time. They are not.