RFC 3339 vs. ISO 8601
ijmacd.github.io
ijmacd.github.io
I don't think it's unreasonable to want to be able to specify a meeting in London, on July 1st 2030, at 6pm local time - no matter what happens to UK timezones between now and then.
The UK currently uses Z+00:00 from November to March, and daylight savings of Z+01:00 from April to October (roughly)[0]. But it's possible that between now and 2030 they might adopt Central European (Summer) Time[1], or retry British Double Summer Time[2], or scrap daylight savings entirely. Therefore, what happens to 6pm with respect to any given epoch might vary wildly between now and 2030.
But it would be nice to set a calendar event for "6pm London time", whatever London time happens to be when the event rolls around. But there's no standardised interoperable way to say "2030-07-01 18:00:00 Europe/London".
[0] https://en.wikipedia.org/wiki/British_Summer_Time
[1] https://en.wikipedia.org/wiki/Central_European_Time
[2] https://en.wikipedia.org/wiki/British_Summer_Time#Periods_of...
A wall clock / human readable time without a TZ is like a…
…a horse without a field?
…a burger without knowing the meat?
…a photograph of a star without a position?
…a lover without a name? Ok maybe too far.
…a bonus without knowing the currency?
But I do love the `date` utility, which allows alphanumeric time zone abbreviations pretty well.
https://en.m.wikipedia.org/wiki/Tz_database
Even this is not enough for some edge cases like “I shall take my supper every day at 6pm, Jeeves” but one can always find exceptions to anything.
The suggestion above is to have the zone in the timestamp. ISO-8601 and RFC-3339 put the offset in the timestamp.
Zone and offset are different concepts: the up-thread comment's poster's example of Europe/London is one zone, that currently has two offsets, depending on time of year.
The up-thread comment includes a very practical example that any app dealing with something like an "appointment" would have to reckon with.
Including fixed UTC offsets was a massive mistake and it should have never happened. Anything except named timezones is useless.
Otherwise, I'm also always left wondering whether they really meant CET or actually CEST, calculating what the current offset of CET is, double-checking whether there's some other CET that I might be confusing things with (China Eastern Standard Time?) etc.
It is only scheduling future events where they fall down. Calendars and scheduling are demanding applications.
This is why I left computer science research. I realized I was working on things that only made sense inside the machine.
Europe/London will be either be left alone for historical purposes, or aliased to its successor for backwards compatibility.
See Type: Link and Source file: backward:
* https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
It could have been Country/City or Region/Country but it's Continent/City instead.
Continents or regions of the world don't change fast or due to politics (not often) and cities aren't renamed or disappear that often, so this scheme is probably a lot more stable than any that uses political entities. (Think about countries that split or rename or become occupied, the locations of cities like Sevastopol (occupation), or Juba (Sudan/South Sudan split) or Jerusalem (every controversy).)
Or what if it's split into two cities, which half were you talking about? This has famously happened with Berlin.
For example, instead of London, suppose you wanted to meet in Glasgow, Scotland, on July 1st 2030, at 6pm local time.
Currently, Glasgow in is timezone Europe/London.
However, it is not unimaginable that in that time, Scotland could hold another referendum on independence and either join Central European Time, or create Scottish Standard Time.
> specify a meeting in London, on July 1st 2030, at 6pm local time - no matter what happens to UK timezones between now and then
GPS coordinates + local date and local time will preserve “a meeting in London, on July 1st 2030, at 6pm local time” in the desired way
That’s the point. Normal people think about time based on their local time. If they agree to meet someone at 3pm on a day in the future, that normally means turning up on that day when a local clock on that day reads 3pm. If local time changes offset from UTC, then the meeting implicitly also changes.
I’ve personally yet to meet someone that reschedules all their appointments every time day light saving (or the inverse) rolls around. Just make sure their appointment times in UTC don’t change.
Then when the meeting time is approaching, the software can figure out what time zone (and UTC offset) applies, after taking account any time zone changes that have taken place in the intervening years, and appropriately set reminder notifications.
If they were to store "X seconds from the time this message was sent", then any time zone change would likely make it not fall at 6pm on the target day, so that's not what they'd want.
The problem is there is no difference between local time and "offset from UTC", right?
The difference is between applying the UTC offset for a future event using present rules. What we are saying is you should not do that because the rules can change.
I ask you today that we meet at 3PM on January 24th in 2026, at the train station in Berlin.
In my paper calendar book for I mark the date January 24th 2026 with the following note: “meet jvanderbot at 3PM at the train station in Berlin”.
I carry this book with me for the next few years.
Meanwhile, you decide to be modern so you store a note about the meeting in a database. In doing so, you convert the information into a UTC offset for that future time. But you are using current rules for today, which may change.
And then when the day arrives, there has been political changes in the meantime that made it so that the utc offset is different.
Because you converted to utc offset ahead of time, your representation of the time no longer maps to “3 PM” but instead to let’s say “4 PM”.
I show up at 3 PM local time, as we had agreed. But you are nowhere to be seen because in your digital calendar the meeting appears to be for “4 PM”.
This is what we mean when we are talking about the problem with converting a local time to a UTC offset a long time ahead.
https://www.972mag.com/the-worlds-only-ethnic-time-zone/
If there's one thing I've learned about time keeping, it's that whenever you think you've got it all figured out, there's always one more corner case.
This is why storing UTC dates for future events is insufficient: if the event is actually specified in local time, the date is incorrect when the time zone rules are changed. But storing the time zone is insufficient if the time zone that applies to the event also changes; you also need to store enough information to reevaluate which time zone is applicable.
Of course, it can be difficult to gather this information in a user friendly way, so you know, compromises.
One could imagine using geo coordinates or similar, but the mapping from those to timezones (or from/to zip codes or area codes) is already not precisely defined.
If you use city names, those might also be split/merged (Berlin) or renamed (Constantinopel).
You could develop a way to specify a location and indicate that you mean 'local time' at that location.
There is actually a good read on this at https://www.ordnancesurvey.co.uk/blog/is-britain-on-the-move
There's 4 things at play here:
- Coordinate location on the planet
- Identifier for that location
- Political entity for that location
- Current timezone policy
Of those, coordinates are the only thing that doesn't change over time (for the spans we're talking about).But are also a pain in the ass to use. F.ex. I'm sure someone on HN has the lat long for London memorized, but I don't.
Coz change like that could fuck some shit up...
[0] https://github.com/eggert/tz/commit/e13e9c531fc48a04fb8d064a...
For example: https://data.iana.org/time-zones/tzdb-2020d/europe (search for Kiev for the specific part; it's a very long file)
[0] https://turismo.buenosaires.gob.ar/en/article/what-where-and...
Time zones are political | * social* especially in the twilight zone between two otherwise well defined zones.
If a country is mostly in TimeZone X then often an extrusion that goes well into TimeZone Y will remain with clocks aligned to TZ-X unless some local political change is made (to be more or less sensible).
See (current TimeZone Map):
https://www.timeanddate.com/time/map/
and note that cities have changed time zones (not daylight savings changes, actual changes to core time zone) in the past and will almostly certainly do so again in the future.
*Every single time* I update the tz source file some arbitrary set of zone names and offsets change. Look at the churn and enjoy the schadenfreude: https://github.com/photostructure/tz-lookup/commits/main/tes...
Not only is that not true, but there are places on the earth where one country may think the timezone is X, but in another country it is illegal to claim that the timezone is X.
This happens most notably with China, which defines the entire country to be in a single timezone, and is engaged in multiple border disputes.
2030-07-01T18:00:00~Scotland/Glasgow ?Or be in the middle of a political dispute, with different times being used depending which side one is on, like Xinjiang. So just knowing the place and local time isn't enough.
I think you need to be more specific here.
And likewise in PostgreSQL you can store timestamp without time zone.
Combine that representation with lat/long gps coordinates and you have what you need for scheduling future events at specific locations regardless of changes in time zone names and offsets.
Whether your calendar software will let you choose how it expresses the timezone and whether the recipient's calendar software will store it that way is another question...
Sadly, iCalendar is very much tied to using timezones for locations. I expect that if/when Europe finally gets round to abolishing DST, there will be some significant changes to the timezone boundaries, and as a consequence, much hilarious calendaring failure. Dunno if it will affect as many people as the 2007 DST changes in North America, which caused a lot of extra work for people running Microsoft Exchange, because it was designed assuming that timezones never change. And this design error carries over to iCalendar, tho (apart from tz boundary changes) it is better than it was.
event://de/Berlin/10557/Platz+der+Republic,+1/Bundestag#2030-08-30T18:00Use GPS coordinates instead :D
International disputes make it difficult to answer a lot of questions about specific locations without making choices about which authorities you’re willing to respect.
Value 0 meaning “if there is a DST switch, interpret the time as the chronologically earlier one”
Value 1 meaning “if there is a DST switch, interpret the time as the chronologically later one”.
But you still need to handle the case where the local time is skipped. You could pick the timestamp during which the skip happens, but that'd lead to an offset that can contain fractional seconds, which almost no datetime library supports.
[1]: https://codeblog.jonskeet.uk/2019/03/27/storing-utc-is-not-a...
If the UK changes its rules before that time, then the timestamp becomes "inconsistent" (see section 3.4). The behavior on an inconsistent timestamp is left for the application to decide, but if a ! character is included within the brackets before the timezone name, then it's at least obligated to detect the problem instead of blindly following the UTC offset:
> In case of inconsistent time-offset and time zone suffix, if the critical flag is used on the time zone suffix, an application MUST act on the inconsistency. If the critical flag is not used, it MAY act on the inconsistency. Acting on the inconsistency may involve rejecting the timestamp, or resolving the inconsistency via additional information such as user input and/or programmed behavior.
This extended timestamp format is used in the proposed Temporal library for JavaScript [1] (though I'm not sure if it supports the ! character). The ZonedDateTime.from() parsing function [2] takes an optional "offset" parameter to allow the user to control which part of an inconsistent timestamp takes precedence. It also supports simply omitting the UTC offset and using only the timezone, but it warns that this is ambiguous for times in the repeated hour during a DST transition.
[0] https://www.ietf.org/archive/id/draft-ietf-sedate-datetime-e...
[1] https://tc39.es/proposal-temporal/docs/strings.html#iana-tim...
[2] https://tc39.es/proposal-temporal/docs/ambiguity.html#ambigu...
` 2030-07-01T18:00:00[!Local] `
Where no offset and the !Local tell the app to use OOB defined location?
2030-07-01T18:00:00~BTC
2030-07-01T18:00:00~CEST
2030-07-01T18:00:00~Local
2030-07-01T18:00:00~Europe/Warsaw
to signify it is not a constant point in time but timezone-at-the-time dependent.This time description in the indicated timezone, at the instant it is correct? (Ignore updates, I mean the time I said. E.G. The doors open at 8am every day.)
An indicated end of a duration, such as the period of time a mass of decaying radio-isotopes are valid for the sensor during? (Offhand, no consumer equipment comes to mind, but for an extremely sensitive calibrated sample it could matter and this is a contrived example.) Exact moment in monotonic time. (What about stretchy leap seconds too?)
Something between the two extremes?
Most humans probably want a default of something like...
"Looser more common use time unless I get more specific." So if a TZ is included, it isn't a fixed moment, but whatever specifier is the valid moment as that moment passes. Convert it to an absolute monotonic value at that time to record the event and not just the specification of when to capture the event's passing.
E.G. Unix time Epoch was 1970-01-01 00:00:00~Z with an absolute reference value of 0s DATE RoundedHour~US.EST => Actually is EDT but most people don't use that notation, and congress changed when DST happens yet again without abolishing it too, and this happened last year before the change but the event did run from Noon to 9PM with these event moment second values...
It would simply mean the time which is intended. It’s true that the instant isn’t known until it happens (or however much leeway precedes a TZ change). It’s generally always better to record intent, than to be smart and translate inputs to something else.
To map to a specific instant in UTC time, you use the string plus a db. The db can change in the future, and that’s ok. You simply update in the presentation layer in case you have any “2h left” strings or calendar entries. Note you should NOT store the mapped instance in a db before the event has occurred (and even then it’s unnecessary since it’s fixed).
I really don’t like the “inconsistent” mutable property and agree with parent that offset should not be part of the format. That would make it extremely easy to overlook or misuse.
Perhaps I’m missing something?
However I'm saying that the solution should be radically different and much more user focused.
There is a difference between a description of when to capture a moment (which should favor the way the normal person describes moments) and an absolute moment event.
Yes, you’re missing something - geography. “Local time” doesn’t include a frame of reference. If you want to have a meaningful representation of local time you need syntax to specify where, probably Lat/Long.
Then, periodically, the computer can look up the lat/long to see what the rules are there for time, and compare vs the target time.
But even THAT doesn’t solve the problem, because you probably don’t want the computer in a tight loop of looking up location rules for time and checking time. But if you do it periodically then there is a nonzero chance that you will miss the event because the rules changed since the last check and the current check happened after the event.
And you can’t just use the city names for time zones (e.g. “Europe/London”) because only a very small number of places have such names, and because they really refer to a combination of time zone and DST rules, not to a city, they just choose representative cities.
Finally, ISO 8601 does support durations, which RFC 3339 does not, so ISO seems more useful in that regard, but durations are not relative to any epoch.
So what happens when a timezone name changes?
Say Manila timezone changes names to New Beijing timezone in the next 10 years (fictive example)?
If the 'Asia/Manila' timezone changes to the 'Asia/Shanghai' timezone, the old timezone will still exist, but a rule will be added to indicate the change.
The tz name here is a specific name in the tzdata database, so it's quite easy for that database to never remove any entries, but to rather deprecate them or link them to new ones, if appropriate.
All our common date time formats are intended to represent a specific point in time and this you just do not have in your case. But it is actually not too uncommon that date and time specifications have a non-trivial structure, think a meeting on every last Friday of the month or a monthly meeting series starting on January 31st or two days before the end of each quarter.
I would guess trying to come up with a standard that covers all the things people could come up with, would become quite complex quickly. So if simple dates, times or instants are not good enough, you are probably on your own, make some structure with all the required things.
Theoretical arguments are nice, but in the real world, meetings are regularly scheduled were one or all people aren't physically at the location, say the company's headquarters, but the local time zone and its DST shifts are obviously still respected.
The only gotcha about such a thing is that there are ambiguous or impossible timestamps: 2023-11-05 01:30:00 America/New_York — that's one of two different times.
For calendaring, it would make sense, since "same wall clock time regardless" is what most people want¹; there might be some UI difficulty/challenges to handle the weird times, and maybe one might want to have a way to specify a disambiguation in the syntax.
Thankfully for calendaring those are usually in the middle of the night, but I've literally seen this happen in my career.
¹though once you invite the first person in a zone that doesn't do DST madness, note that this causes the calendar time to wobble on their calendars. Some of my international coworkers have to put up with this.
But when CA switches to PST (Pacific Standard Time) the meeting shifts to 8AM for the people in CA.
But if the people in CA lead, and always want the meeting at 9AM local time, then the meeting for the people in Phoenix will move from 9AM to 10AM and back.
Can't have it all.
Part of what makes TZ discussions incredibly difficult is that people play fast and loose with the terminology.
I think the person you're responding to is simply saying that if you made the meeting in a non-DST observing zone, the meeting time would still wobble in a DST-observing zone. (I'm not sure why they're noting it, because my comment also clearly spells that out, too, albeit in reverse. But yes, it works both ways.)
I know it works both ways, too, but probably would be better for the DST observing zone to deal with the effects of DST, instead of foisting such side effects onto our international friends.
This takes a bit more effort, but it is less ambiguous and saves you from having to deal with the insanity that is time. DST switching will still cause issues but, as long as you're not the one cursed to implement that software, it should be fine with advance warning.
Yes, and maybe East London secedes from the UK and uses a different time zone, so Europe/London doesn't specify the time zone you meant, anymore. This might not be likely for London, but if it's in the countryside of a less stable country and you just specified the time zone as the capital city, this might happen.
I prefer time formats that are actually implementable and don't depend on a large database that can change at any moment.
Countries change. Timezones change by decree. This is a pain but it’s the real world and our tools need to be able to deal with it. I don’t like it either, and no one cares, nor should they. Reality trumps preference.
The tz database is updated on average every two months, and that doesn't happen without reason. Countries keep changing their timezones, and a rather high-profile one is the European Union's plan to get rid of DST over the next few years. This is already happening in Greenland this year. Some Muslim-majority countries also like to make their DST depend on Ramadan - which falls on a different and somewhat unpredictable date every year.
Like it or not, if your code uses future dates and does not rely on "Europe/London"-style timezones, you will be slowly corrupting your data.
How so? 2030-07-01T18:00:00+01:00 is a well-defined point in time, is it not? It may or may not be local time in London, but it's unambiguous.
July 1st 2030, at 6pm, Europe/London is not. What's broken is the idea that you can somehow standardize "local time at a particular place" in a way that magically survives any arbitrary policy change.
> Some Muslim-majority countries also like to make their DST depend on Ramadan - which falls on a different and somewhat unpredictable date every year.
Thus proving that what you want does not exist and cannot exist.
Being unambiguous isn't helpful if it is wrong. It is a very common desire to want to set a meeting based on the local time of a destination. The only future-proof way to store such a time, is to remember the destination and the desired local time. This is the only way the proper moment can be calculated and kept in sync with reality.
The unfortunate fact is, the local time could be altered by decree, in any number of ways, in the interim timespan between setting a reminder, and when it happens.
It's a redundant way of writing 2030-07-01T17:00:00Z which only serves to cause confusion (it misleadingly looks like a local time, but it isn't). TAI or equivalent are useful; symbolic timezones are useful; numeric time offsets are useless and there's no benefit from having them be part of the standard.
> Thus proving that what you want does not exist and cannot exist.
Of course it does; 2030-07-01T18:00 Africa/Casablanca is a real time that humans will have no trouble attending a meeting at, and nor will computers as long as they've been keeping their zone file up to date. All we need is a standard for storing and interchanging it on computers.
No, the reason people use it is because they don't want to add the timezone offset and want a timestamp that's intuitive.
Not consciously. But they think it's always going to match the time on the clock in their office / on their town hall / on their phone. No-one deliberately writes a time in the time offset corresponding to their local winter time for an event that will happen in their local summer time (or vice versa).
> want a timestamp that's intuitive.
I don't know about "intuitive", but they want to write times in their local civil time.
True, but unfortunately humans only care about local time. Setting a meeting for "6PM London time" is how pretty much the entire world operates. If your app can't deal with that, your app is doing it wrong. The world doesn't care that it isn't "well-defined", as developers we just have to deal with it.
> Thus proving that what you want does not exist and cannot exist.
But it does exist, and many calendar apps operate exactly like that. It just requires them to update their timezone database every few months - which in many cases already happens automatically as part of OS updates.
"2030-07-01T18:00:00+01:00" conveys no more information than "2030-07-01T17:00:00Z". The UTC offset is meaningless because it is impossible to get a timezone from it, so it cannot be fixed in the future. It essentially screams "we tried to do local time and failed".
2030-03-24 01:30:00 Europe/London seems like a perfectly reasonable time stamp. But if the UK decides to move BST forwards by a week between now and 2030, that time won’t ever happen.
What's unreasonable is wanting this to be one piece of information.
Location and time are distinct concepts that need to be split up.
A timezone is not a location. Timezones are just a subjective shorthand convenience for display purposes, not actually tracking time. The reason the abstraction sucks is because the idea sucks.
Got it in one. Relativity, universal time, the human circadian rhythm...
To quote my all time favourite HN comment quoting Plautus (presumably taken from R.R.J. Rohr's 1970 Sundials: history, theory, practice):
> The gods confound the man who first found out how to distinguish hours! Confound him, too, who in this place set up a sundial, to cut and hack my days so wretchedly into small portions! When I was a boy, my belly was my sundial — one surer, truer, and more exact than any of them. This dial told me when ’twas proper time to go to dinner, when I had aught to eat; But nowadays, why even when I have, I can’t fall-to unless the sun gives leave. The town’s so full of these confounded dials the greatest part of the inhabitants, shrunk up with hunger, crawl along the street. — Plautus (c.254-184 BC)
When I worked on a system that provided schedules for appointments, it was quite difficult to furnish a link that put this on someone's calendar reliably, and to set up reminders that went out every third Monday of the month at 9am to remind people to go to their clinic appt at 11am. People are equally annoyed at 8am or 10am reminders in such a case, so you can't tie it to a specific time, and daylight savings time gets changed from time to time, and various locations have "9am" at different times. We didn't even get into the weeds of whether someone who lives in Phenix City, AL should get notices in Central or Eastern (it's Eastern for most people, except if they work for the government or are going to school... unless it's a private school, which might still be on Eastern...).
Telling someone they can get their notice at any time they want as long as it's specified in UTC year round just doesn't solve the problem they have.
The date can be stored together with the time as a timestamp, but all timestamps need to be in UTC. Getting the user's locale and applying their timezone is done on the client side. What matters to people stays on the client side.
Date time + lat/long?
- https://github.com/kstenerud/concise-encoding/blob/master/ct...
- https://github.com/kstenerud/concise-encoding/blob/master/ce...
e.g.
2019-8-5 // August 5, 2019
5081-03-30 // March 30, 5081
-300-12-21 // December 21, 300 BC (proleptic Gregorian)
20-01-01 // January 1, 20 (NOT 1920, NOT 2020)
09:04:21 // 9:04:21 UTC
23:59:59.999999999 // 23:59:59 and 999999999 nanoseconds UTC
12:05:50.102/Z // 12:05:50 and 102 milliseconds UTC
4:00:00/Asia/Tokyo // 4:00:00 Tokyo time
17:41:03/-13.54/-172.36 // 17:41:03 Samoa time
9:00:00/L // 9:00:00 local time
2019-01-23/14:08:51.941245 // January 23, 2019, at 14:08:51 and 941245 microseconds, UTC
1985-10-26/01:20:01.105/M/Los_Angeles // October 26, 1985, at 1:20:01 and 105 milliseconds, Los Angeles time
5192-11-01/03:00:00/48.86/2.36 // November 1st, 5192, at 3:00:00, at whatever is in the place of Paris at that time
1985-10-26/01:20:01.105+0700 // October 26, 1985, at 1:20:01 and 105 milliseconds, UTC+7:00
2000-01-14/10:22:00-0200 // January 14, 2000, at 10:22, UTC-2:00
ISO 8601 and RFC 3339 are fine for dates in the recent past, but they're not great as a general time format.Define whatever format you want, and there's always the possibility of a politician changing what the local time is.
Historically, the offset against UTC has changed by a few minutes, hours, or days. Is daylight savings used? When? It is not even certain that it is the same calendar that is used, or that there are 24 hours per day, when the day starts, which months there are, or which month is the first of the year.
If the time zone changes in the future, so that the specified local time no longer corresponds to the same time in UTC, then the time of the event has changed, even if the organizer still specifies 6 pm.
There are disadvantages too of course, one of which is overlap between airport codes and currently existing timezone codes. This led me to discover a couple of airports that have the same code as their timezone.
It is an extreme example but if you look at e.g. certain parts of Africa or Middle East…
It makes sense to me that it is not provided as it is something fundamentally different. ISO 8601 / RFC 3339 are just textual representations of specific[*] time moment (or interval), that could be easily converted to different definitions of time moments.
OTOH, specifications like '2030-07-01 18:00 local time in London' are not a definition of a specific time moment, the are really a description of a condition, and we cannot resolve it to a specific time moment before it happens.
So these are two fundamentally different concepts that does not make sense to put into one category.
[*] If we ignore leap seconds
Also, if you are working on anything dealing with date in the future, you nearly always want to store wall clock time + location. Sadly, there is no standard for that.
In Europe and USA the timezones are quite stable, so we might not be confronted to this, but in many places timzones change quite often, and storing an offset is not stable. Having "june 5 2026, 13h30 wall clock, paris" is what most people will mean, and it might be UTC+2 or UTC+1 depending if EU finally decide on what to do with DST.
And finally, if you write an API with times in the past, just use POSIX timestamps in seconds, ms, us or ns.
iCalendar is an RFC standard for this. [1] Note that some times have two representations and some times are not representable in this format when there's a time change due to DST.
iCal also does not contemplate a location being reassigned to a different time zone, an issue discussed elsewhere in this thread.
Of course, properly formatted iCal files also include data for all of the referenced timezones. Which makes it cumbersome if you just wanted to output a single datetime.
[1] https://icalendar.org/iCalendar-RFC-5545/3-3-5-date-time.htm...
https://www.ietf.org/archive/id/draft-ietf-sedate-datetime-e...
It certainly doesn't list all places, but it lists most of the key ones that have carried weight on timezones, and is about the best database a lot of internet nerds have managed to accumulate of a lot of the complexity of current (and historic) timezones by roughly place name.
See http://xml.coverpages.org/ISO-FDIS-8601.pdf (section: 5.5.4.2 Representation of time-interval by duration only, pg. 21)
Would like to see more json parsers in static languages allow me to define a field as a time span and can serialize into the valid format.
For an example, see this proposal in Crystal: https://github.com/crystal-lang/crystal/issues/11942
Example: A duration of 15 days, 5 hours, and 20 seconds would be:
P15DT5H0M20S
A duration of 7 weeks would be:
P7W "duration": {
"days": 15,
"hours": 5,
"seconds": 20
}
Now it's not the job of your JSON parser to understand the semantics of your data. It's your input validator's - which is how it should be, imo.Note you will have to have some fallible conversion step from whatever JSON chooses to represent that data as anyway.
2023-08-24T20:30:00Z
versus "time" : {
"year" : 2023,
"month" : 8,
"day" : 24,
"hour" : 20,
"minute" : 30,
"second" : 0,
"timezone" : "UTC",
}
Call me lazy, but tryping the latter took me 20 times longer. I totally would use it for internal state, but I would not store it like that or expose that to users ever.Durations optimized for storage without ambiguity would be the tuple (u64, u32, u8) where the first value is seconds, second value is nanoseconds (if precision is needed) and final value is epoch.
Durations displayed to a user wouldn't ever be stored so the point is kind of moot.
Optimizing for "time it takes someone to write it once" is kind of dumb since it happens once while reading it happens often, and parsing even more likely.
And it's really nice in some circumstances (such as the file names case) that alphabetical sort is identical to chronological sort.
And just... why would you spend 10x the space to represent timestamps when ISO timestamps (or, well, RFC 3339) works just fine?
With your example, I would need to create custom parsing logic, and handle a dynamic number of JSON fields. But if a TimeSpan class had JSON deserialization built in based on the ISO8601 format, then I wouldn't need to do anything special. That's the benefit of using the standards. Same if I wanted to convert the JSON stringified format into a postgres time span there isn't any special parsing logic I need to do.
Yes, it's just a string in JSON, so it's not semantically special. But other languages that have a TimeSpan type could take advantage of the standard serialized format.
Here is an example of what it could look like in F#, no special logic for deserializing into a custom type:
type MyEvent = {
myDuration: TimeSpan;
createdAt: DateTimeOffset;
eventId: string;
}
let rawJson =
"""
{
"myDuration":"P15DT5H0M20S",
"createdAt": "2023-08-24T20:30:00Z",
"eventId": "e_1234"
}
"""
let myEvent = JsonSerializer.Deserialize<MyEvent>(json = rawJson)But either way you need multiple pieces of data for the duration to be correct and useful. Without the created-at time in your example the duration will be invalid in the presence of leap years/seconds.
If you want to unambiguously encode a duration of time, it needs to be in the smallest unambiguous unit that is meaningful (usually seconds/nano seconds). That will allow your duration to be correctly used without any additional logic/metadata packed along with it.
Alternatively, simply refer to the ABNF definition of “duration” in RFC 3339, Appendix A.
Also, both standards are very unclear on how to represent DTs BC, and how to represent DTs after 9999-12-31 (or before -9999-01-01), and most commonly used libraries often just cannot handle them at all. And even when they can, the behavior of 00-01-01 is basically undefined (may I remind you, that Gregorian calendar is stupid, and the next year after 1 BC is 1 CE). In short, basically no software except for specialized astronomical software handles anything beyond near-future unix-time, even though for most purposes (like, uniformly representing DOB/DOD of Emperor Augustus) it's really not rocket science (we are really ok with just storing strings) and just needs to be clearly defined in some standard!
It's much readable too. I recently started ignoring both standards in favor of the nicer space-separated format after almost two decades of sticking with the former. I get why they needed a non-whitespace character but they could have at least used an underscore or a dot.
And I have no idea why they sacrificed the universality of the format by limiting the year segment to only four digits. It's a string!
> And I have no idea why they sacrificed the universality of the format by limiting the year segment to only four digits
No, there are reasons. People often represent year with 2 digits, so forcing you to use 4 digits is basically intended to make representing 20 CE unambiguous as 0020-01-01 (as opposed to 20-01-01). But, I mean, it's a problem to be mindful of when making a standard, not an insurmountable obstacle. A real standard to end other formats once and for all just needs to make sure to take care of all corner-cases. The truth is RFC 3339 and ISO 8601 are just shitty standards.
(Edit: Also, just in case, note that it is possible to use 5 or more digits in ISO 8601. But the standard says that the parties must agree beforehand on that. That's what I mean by "unclear". I cannot just say that you MUST represent DT in ISO-XXXX format, it's not specific enough. In the end we must to agree on how our systems will behave when receiving this or that value anyway, so it makes having an external "standard" pretty pointless, since the standard is pretty clear about very obvious situations, and very hand-wavy in all actually non-trivial situations.)
Ambiguously. I've seen a lot of different cutoffs, including 1930, 1950, 1970 and 1980. And those cutoffs don't actually exist in the human conversation: I would guess the century, and if something sounds off, I'll ask the exact year number and get corrected or verified. Computers can't do that (or at least, should only do in the frontend).
> I cannot just say that you MUST represent DT in ISO-XXXX format, it's not specific enough.
Laypersons have no idea what the heck is ISO 8601 anyway. I'd just say: use the format "yyyy-mm-dd hh:mm:ss", padded with enough zeros. Then I'll parse it as if ISO 8601 date and time format with the `T` omission is allowed (because it essentially is). Done. I wouldn't ever try to figure out the meaning of, say, `23-09-01 12:34:56` because they are ambiguous and should have been discouraged after all (or more practically, allow a free-form format but give the guessed normalized date and time in ISO 8601 immediately so that it can be checked).
Damn, that's a great point for sure. Then what's the point of having a standard if "nobody has any idea" what it is and and you are supposed to define all the details of the format with all corner-cases in a private conversation anyway?!
That's right, there's none. The whole point of having a standard is that I can say that the value is "ISO 3166-1 alpha-2" country code, and you know that you MUST recognize all officially assigned values (or you don't really implement the protocol) AND that you'll never receive, say YY, unless ISO assigns it a value (or it would mean I violate the protocol). Now, just to be clear: this standard is also not as well-defined, as I'd like it to be — since some values can be user-assigned, and in effect 2 different implementations of "ISO 3166-1 alpha-2" can be incompatible. And I don't really see the point of referring to a changing standard without specifying a version. But it's as good as it gets here, and is totally enough for 99% of cases where you'd need country codes.
ISO 8601 is way worse, since it doesn't unambiguously cover even relatively basic use-cases of how people use dates, and in effect we have lots of "somewhat ISO 8601" protocol implementations that are incompatible, and it cannot be clearly communicated what is the actual scope of your implementation by linking a sub-standard, and in the end you have to "just say": use the format "yyyy-mm-dd hh:mm:ss", padded with enough (what does "enough" mean, by the way? no clue) zeros. I.e., you have to not to refer to any standard at all. And given ISO 8601 is also clumsy as hell, most people prefer to use home-baked format anyway.
Because they are often building blocks for other standards, not necessarily to be used directly.
For example there is an ISO standard called ISO/IEC 5218, "codes for the representation of human sexes", and it is simply 1 for male, 2 for female, 0 for not known and 9 for not applicable. So should the male called the sex 1? Not at all. It exists because many existing databases used such values for sexes (or genders, whatever they are). If you are not benefitting from using ISO/IEC 5218 and there is no associated legal requirement then you have no obligation to use it. Same for ISO 8601 and pretty much every standard.
If you want to create a forgiving enough date and time format that aims to be adopted as much as possible, go ahead, but ISO 8601 doesn't have to do that.
> [...] in the end you have to "just say": use the format "yyyy-mm-dd hh:mm:ss", padded with enough (what does "enough" mean, by the way? no clue) zeros.
You are correctly guessed that this description is not for everyone :-) (For example, I haven't said that it uses the Gregorian calendar.) ISO 8601 does cover that. But not everyone has to fully understand ISO 8601 to write an ISO 8601 date and time---we can just tell a (typically small) difference between the "common" format and ISO 8601.
> [...] in effect we have lots of "somewhat ISO 8601" protocol implementations that are incompatible, and it cannot be clearly communicated what is the actual scope of your implementation by linking a sub-standard, [...]
"ISO 8601 date and time format with the `T` omission is allowed" is a concise and complete description and not "somewhat ISO 8601". The standard explicitly says that parties can choose to pick this extension, meaning that the standard itself works well whether the extension is used or not and other defined extensions won't collide with it. This is different from something like "the format yyyy-mm-dd" for the reasons I've detailed above; it is okay as an explainer, but not enough as a specification.
I do think though that ISO 8601 will benefit from explicit labels for those extensions.
Look… How often are you referred to ISO/IEC 5218 standard, honestly? Me — it very well might be that you're my first. But it's nice it's there. If it wasn't, I wouldn't be very sad, because M/F/None was probably enough for me so far (and is actually way more permissive than most of actual protocols where I had to specify human sex, which usually allow just M/F).
ISO 8601 on the other hand… First off, datetimes are everywhere, and are used constantly. Second, datetimes are far less trivial, and it actually requires some good amount of thinking to come up with a good representation. It is even more complicated to communicate that specification in all of the details. So, forget about whether ISO 8601 exists or not — the fact is, that I need a datetime standard. I need it every day, many times a day. Everyone needs it. Everyone comes up with his own shitty standard at least a couple of times during his life. Nobody can really communicate his own shitty standard unambiguously, covering even most popular corner cases, because only very rare people actually thought about the problem half as much, as it has to be thinked about to come up with something remotely good. And since pretty much everyone even acquainted with a notion of "standard" regards ISO as the "standards organization" we end up referring each other to ISO 8601 often enough that I know what one is talking about without actually googling the code. Technical people almost consider it a virtue of not coming up with their own standard, if there already is a usable one (and for a good reason). Long way short: ISO 8601 is important. Way more important than ISO/IEC 5218 or some meme tea-making manual. And it doesn't live up to what is (and, my point — should be) expected of it.
The range of what HTML allows is far more used in practice, in my experience. Which is kinda sad, because "HTML date format" isn't really format I should be referring to, ever, it's ambiguous, it's not commonly recognized, and it doesn't even account for a number of very important use cases ISO 8601 accounts for (date ranges, for one).
Now, I'm not sure which part of your post would I quote, but basically you are missing my point in the whole second half of your post. You are spending a lot of time talking about "T vs space" (which, unfortunately, might require that much time talking about and more), while this is really the trivial thing, everyone would get on the go, since it's so commonly used. So, because it's so intuitive, it's the part of the problem that begs about being standardized the least. What really begs for a standard are all these less obvious situations: 2-digit years, years before 1582, years BC, years after 9999 — which, unfortunately, are really not that uncommon. Honestly, they are common, even.
And while — as I said from the very beginning — ISO 8601 does make some half-assed attempts to address all these issues, in practice it doesn't communicate any of possible scopes of values clearly enough. In effect, there are lots of applications, that pretend that they "parse ISO 8601 datetimes", yet you'll find out that, say, Python standard library just doesn't handle negative dates at all. Which is ok (I mean, bad, but understandable), but the problem is that you really have to think about it yourself to even find it out. And the big value proposition of having a standard is exactly that you don't have to think about all the details, you just rely on the fact that Wikipedia (a big, reputable project) claims that it uses standard X for the datetimes, and Python (a big, reputable project) claims that it's standard library function can parse standard X datetimes, and you just assume that someone did all the thinking for you already and they are compatible. And ideally there should be standard Y such that it makes it trivial to refer to X = Y-1 and X = Y-2 and see that they are, in fact, incompatible.
So in practice ISO 8601 just doesn't do what it should.
RFC 3339 does allow the format "2023-09-20 20:30:59Z", which is more readable, although it requires either the "Z" specifier or an offset like "+00:00" at the end.
From the RFC:
> ISO 8601 defines date and time separated by "T". Applications using this syntax may choose, for the sake of readability, to specify a full-date and full-time separated by (say) a space character.
You can also verify this with the validator on the website OP linked.
ISO 8601 does allow for that format given a mutual agreement. The "mutual agreement" sounds serious but means nothing more than a simple qualifier like "ISO 8601 where `T` can be replaced with a space" (RFC 3339 also does this in a much wordy way). I don't think how this makes things unclear, esepcially when people generally are unaware of ISO 8601 anyway.
> [...] which is by far most used DT format (because it's fucking obvious!) across all systems [...]
I'm not even sure that this is the most used date-time format. The most spoken language is Chinese, for which native separators like 2023年9月1日 are common.
> Also, both standards are very unclear on how to represent DTs BC, and how to represent DTs after 9999-12-31 (or before -9999-01-01), and most commonly used libraries often just cannot handle them at all.
Again ISO 8601 allows for year numbers before 1582 (yes, they are not allowed by default) or after 9999 given a mutual agreement. Such numbers should be prefixed by a single sign character if it can't fit within 4 digits. They are generally not supported because we can't really do anything meaningful with that past or future date, but nevertheless I have seen enough libraries that do parse them (particularly common when they are implemented independently from C <time.h>).
> And even when they can, the behavior of 00-01-01 is basically undefined (may I remind you, that Gregorian calendar is stupid, and the next year after 1 BC is 1 CE).
It is defined as January 1, 1 BCE. ISO 8601 clearly states that its year number is for the proleptic Gregorian calendar, so it infinitely extrapolates back to the negative infinity.
ISO 8601 does not permit that format.
> By mutual agreement of the partners in information interchange, the character [T] may be omitted in applications where there is no risk of confusing a date and time of day representation with others defined in this International Standard.
I thought this allows a replacement of [T] with a space, but it doesn't state so! It just means that the time designator can be omitted, e.g. 2023-09-0117:12:30 instead of 2023-09-01T17:12:30. It does look very strange (especially when used with extended formats) and I'm not sure if it was actually intended or not as there is no accompanying example, but nevertheless the 2016 spec doesn't allow a space. Oops.
EDIT: It indeed seems that ISO 8601-1:2019 no longer has this note. I now agree that this is a bad move. https://stackoverflow.com/a/9532375
[1] Specifically the Draft International Standard that was once available from loc.gov.
You are correct that previous editions allowed omission of the 'T' in DateTime expressions. ISO 8601:2004 (the most recent version before ISO 8601-1:2019) states in § 4.3.2:
> NOTE By mutual agreement of the partners in information interchange, the character [T] may be omitted in applications where there is no risk of confusing a date and time of day representation with others defined in this International Standard.
This was removed with the 2019 version. However there is another section in the latest version which some people get caught out by. ISO 8601-1:2019 § 5.3.5 states:
> In time-only expressions, UTC of day expressions and time of day with time shift expressions, the time designator [“T”] may be omitted in the representations defined in 5.3 only when there is no risk of confusion.
This only refers to Time expressions (not DateTime) and says that both "T16:40" and "16:40" are valid time representations.
"Hey, this guy had set his reminder to today. I wonder what he'd think if he knew we actually saw this 56,000 years later"
"Well, let's regenerate him and ask"
Let's say you run a climate calculation for long enough for example. Now you could just say "fuck dates" if they error — but wouldn't it be kinda nice if they didn't?
Part 2 of the standard gives examples of years with 10 digits.
(I can definitely see cases where 6 digit years would be useful, tho)
This is incorrect. What ISO 8601 actually specifies is that, if the target character set is based on ISO/IEC 646 (which definitely includes Unicode), then a hyphen-minus character should be used for both cases. There is a slight ambiguity here (e.g. what if some charset contains most but not all characters in 646?) but in the case of Unicode the interpretation is clear. I believe this is a roundabout way to specify the canonical mapping for 646 and guarantee the compatibility with other charsets based on 646.
The relevant paragraph from the standard is in ISO 8601-1:2019 §3.2.1:
> All characters used in date and time expressions and representations are part of the ISO/IEC 646 repertoire, except for “hyphen”, “minus” and “plus-minus”. In an environment where use is made of a character repertoire based on ISO/IEC 646, “hyphen” and “minus” should be both mapped onto “hyphen-minus”.
And as you correctly state, Unicode is based on ISO 8859 which is based on ISO 646. So it would seem the intention really is to use U+2D hyphen-minus when Unicode is the character set.
I'd prefer to use space (or underscore) instead of T to separate the date and time parts, but generally stick with T to avoid problems with anything that can only handle ISO 8601 (and to be consistent).
1) What is the reasoning behind 6 digit years? Surely any system contrived today will not exist in the year 100,000.
2) ISO 8601 is prolific. Is RFC 3339 well used/adopted in any system?
Admittedly I've not worked with Golang or Rust, and my Python has been limited to scripting more than developing.
ISO 8601 was first published in 1988. RFC 3339, while ostensibly dated July 2002, codifies practices that date back to Usenet and e-mail (RFC 822: August 1982), and perhaps to the date utility (which existed in Version 1 AT&T UNIX).
I don't know about you, but I think RFC 3339 dates are much more appealing :)
Given that electronic computing has only existed since approximately the 1930s, it's probably premature to worry about what will happen 8,000 years from now.
90% of the time when a library says ISO 8601 it doesn't actually implement the more esoteric parts of ISO 8601.
Whether time is used for a private application or for a standard, the important part is the agreement on what information is being conveyed and in what format. Receiving just the week of the year when you were expecting a time range is not useful.
Likewise, having some sort of official support for "20" as identifying the century (say via a Century type) is a lot of code to carry around and maintain - especially before there's a business need to represent centuries. You tend to need full date time instants, then maybe dates and times independently, then maybe durations - with only a few applications tending to need things like ranges.
Yeah, this means that when you want to use ranges and choose ISO 8601 as your format, you may not find readily-available, off-the-shelf parsers.
But ... I want someone to put together a simulator that can estimate where Voyager 2 will be at e.g. 020000-01-01
Part 2 of the standard gives examples of years with 10 digits.
It was a long time ago but I have memories of Apple's Objective C frameworks not supporting huge swaths of it. And it's worse for private systems that can just tell the clients to keep it inside the generic formats.
In that sense, ISO 8601 or RFC 3339 are virtually the same for many systems/companies.
$ date
2023-08-31T11:15:00-07:00±NNNN is valid (without colon) if used as part of the "basic" format. i.e. no hyphens or colons anywhere in the format.
Thus the following are equivalent and both valid:
2023-09-01T09:40:01+08:00
20230901T094001+0800> Unknown Local Offset Convention
> If the time in UTC is known, but the offset to local time is unknown, this can be represented with an offset of "-00:00".
> This differs semantically from an offset of "Z" or "+00:00", which imply that UTC is the preferred reference point for the specified time.
`Z` should have been used to represent the unknown local time case, and `-00:00` shouldn't exist, while `+00:00` could be used if UTC is the preferred reference point.
In practice `Z` is already used for the "no preferred local time" case very often.
https://community.apache.org/committers/consensusBuilding.ht...
I wonder if that convention had something to do with this choice of syntax.
iCal uses the Z to indicate times intentionally in UTC as well, as opposed to times without a time zone indicator (use unknown local time), or times with an explicity time zone indicator.
Using Z to indicate 'please use whatever local time seems appropriate' seems like poor practice, even if it's a common one.
While when using an explicit time offset, `+00:00` doesn't appear particularly special or more common than other offsets, so I don't think a shorthand for this case is useful.
Another example is that a date can't be converted to a range of instants in times (the first and last second within the day) without knowledge of where it is observed. Games for instance will measure this at some business-decided timezone (say UTC or the timezone of their first server), because having events time out at different times for different people is much more complex.
So when representing an instant in time, a UTC shortcut is easier - if people agree that times are shared with a Z offset, then you simplify parsing. However. there are reasons people would also want a fully specified point in time that preserves a timezone offset as well.
Nautical time has also used Z/Zulu for 0-offset since before World War II.
In practice `Z` is already used *wrongly* for the "no preferred local time"Does anything in practice care about + vs. - 00:00, though? Seems kind of unlikely to be widespread. Among other reasons because people don't know about it. I think if anything I'd have just left the concept out entirely.
2023-08-31/28
I don't think that's valid, as the abbreviated form allows excluding identical parts, so expanded this is 2023-08-31/2023-08-28
which has the start time after the end.Anyway, can someone with more experience tell me when the huge ISO 8601 would be of use over RFC 3339?
I can't imagine any application using 1% of the random formats available.
https://www.reddit.com/r/ISO8601/comments/mikuj1/i_bought_is...
RFC 3339 is managed by the IETF, and their documents are accessible free of charge.
Or from your national member body, which for some standards and countries can be substantially cheaper.
It can represent a month without a day ("April 2024"), and a year without a month ("2024").
In some countries week numbers are used for various purposes ("School starts in week 33 of 2024", "Recycling will be collected in odd-numbered weeks.").
I don't know much about the context, but I remember that datetime parsing code in Firefox was one of the messiest parsers around:
https://searchfox.org/mozilla-central/source/nsprpub/pr/src/...
(I guess that means that at least in the context of browsers, it's far from standardized)
[1] https://262.ecma-international.org/#sec-date.parse
[2] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
This is extremely cool and useful overall, but unfortunately the Venn Diagram seems to be slightly misleading.
The format you spotted in the Venn diagram was:
2023-09-01T10:12:07.284307
This is indeed only valid under ISO 8601 since RFC 3339 always requires a timezone.So the Venn diagram wasn't wrong, but I agree it was misleading.
I've now updated the diagram to add the following format, which is valid under both standards:
2023-09-01T02:12:07.284307Z