I'd like to see the JavaScript people, the Java people, the PHP people, the Perl people, the Python people, the C people, the C++ people, and the people for every other significant language that supports functions (either directly or as methods on objects) to get together and once and for all agree on how the heck we are supposed to deal with times and dates.
Then all of them should implement that in their standard library, so that going forward we've got one sane conceptual time handling system everywhere.
I tire of dealing with the quirks of everyone having their own approach.
These are similar problems: getting a computer-amenable model of something that's fundamentally a human phenomenon, and carries multiple centuries and multiple continents of accumulated context, ambiguity, and edge-cases. This is an extremely difficult class of problems, but in the case of text & characters, we managed to finally get a pretty well-functioning and broadly-supported solution after a few decades of gratuitously-incompatible half-solutions. There's hope.
For a serialisation format, I like the Ts, because it sometimes makes munging data with cut and awk and so on slightly easier. I'd agree it's not a great display format, but then I don't think it's supposed to be.
Right, and it's distinctive, which sneaks type information past all the gremlins in your pipeline determined to strip away any and every bit of context they find in your data. On the whole I think it's probably for the best, but it is ugly.
It's pretty horrible. Apart from being hard to read (why pick an uppercase later that looks similar to numerals?), it only works for full dates or times or datetimes. You can't have literals for just years, or just hours, or just a a particular month. Even 10:20 is ambigious -- is that twenty past 10 (am), or 10 minutes 20 seconds past the hour, or a duration (iso also covers durations, but they are weird and clunky)?
Compare 2020-7-29T19:45 to Chinese style:
2020年7月29日19時45分
Easier to read and you can pick any subset of components unambiguously.
ISO-8601 does not allow replacing the T with a space. You are thinking of RFC 3339 “Date and Time on the Internet: Timestamps”, a profile of ISO-8601 that does allow replacing the T with a space.
> NOTE: 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.
Almost everything should be capable of parsing and outputting ISO 8601 dates [1] today. About the biggest recommendation that still seems to lacking in documentation is that you should probably consider offsets (Z or -0500 etc) required rather than "optional", and that you have to remember that offsets are not timezones (and that generally you should store offsets as presented rather than convert between offsets; makes it easier to adjust offsets based on timezones).
> consider offsets (Z or -0500 etc) required rather than "optional"
ISO8601 without an offset is semantically different to one with an offset, it represents a time in local timezone (context-dependent). It isn't an "optional" offset in the sense that you can just omit it, it is a fundamentally different data type.
Without this distinction, there is no way to specify a local time in ISO8601, which would be highly inconvenient for certain applications. For example, how do you represent an event that occurs at 9am every day regardless of location? After all, dates and times are used for more than just storing absolute timestamps.
You are absolutely correct that offsets are also not timezones, which makes the ability to specify local "floating" times even more important (i.e. you can't just denormalize the above concept into a list of timestamps with offsets for each timezone you care about, as the offsets will change over time [edit: and tz->offset conversion is lossy and not reversible]).
personally I think the mistake is trying to fit both purposes into a single format or type. as you state, it's a fundamentally different data type. representing a fixed moment in time is hard. representing a "floating" time of day is hard. trying to do both with the same type is pretty insane, but unfortunately common.
It wouldn't really be much different if we had ISO8601.1 and ISO8601.2, would it? The standard can define two different types, and it makes it clear what it means to have a time without an offset specifier. It also defines formats for durations, intervals, and repeating intervals.
Is the distinction in representation too subtle?
We accept this subtlety elsewhere; we are used to 0 and "0" being different things, and expect them to behave differently under operators. Few would find the following surprising:
0 + 0 == 0
"0" + "0" == "00"
Then why would we expect these to behave the same?
Good point, which is why ISO 8601 does have a very different duration format (though the options for it such as calendar weeks make it a lot more obvious why it isn't just HH:MM:SS).
Maybe there should be a "float" offset marker. Another thing I was reminded of is that +0000 offset should be Z (UTC), but it is often application dependent if -0000 offset is also Z as some applications use -0000 for "user local time, regardless of user". Which is related to "floating", but yet another semantic difference.
I haven't run into that use of -0000, that's insane.
I suspect a side-effect of libraries lacking support for the full range of ISO8601 (for example, refusing to parse a value without an offset, forcing people to use such hacks).
Wouldn't surprise me; iOS doesn't even have a consistent way to parse ISO8601 values with and without milliseconds.
Negative zero offset is invalid in ISO8601, but valid and carries the meaning you describe in RFC3339. I misread what that meaning actually is from your comment - it is different to a "floating" or unqualified local time, it always represents a UTC time but with an unknown local time offset.
]
From what I can tell, there's no library to parse the full range of ISO 8601 in Python. The standard string that people claim is "just ISO 8601" ("YYYY-MM-DDTHH:mm:ss.sssZ") is not full ISO 8601 compliance.
ECMAScript specifies "simplified extended ISO 8601", which is just that string above.
Reminds me of some of my difficulty convincing old C# developers to break years of DateTime habits and move on to DateTimeOffset. One round trips ISO 8601 directly and the other uses "magic" (DateTimeKind) that is sometimes (likely) wrong.
That also reminds me that .NET documentation likes to pedantically remind me that what I think of as ISO 8601 is probably more specifically IETF RFC 3339, which defines a formal BNF grammar as ISO didn't think to do that in the 80s. (Yay, standards.)
Python adds a nice twist on making time parsing confusing. It has two strptime implementations. There is time.strptime and datetime.strptime. The former has much more limited timezone handling than the later.
It took me quite a while staring at Stack Overflow answers and my code, wondering why the SO answers supposedly worked and my code did not, before I realized I had time.strptime and they were using datetime.strptime.
Not every point in time refers to a timezone.
If I write that 1 january 1970 was an eventful date, I can't/dont want to add a timezone to it. Then you may want to store/format times without dates, etc...
One would think, but it's inconsistent unfortunately. Most platforms have input and output of ISO 8601 but they are less interoperable than you would expect. PHP's claimed ISO 8601 parsing is completely inadequate; it consists of a single format string. Postgres's ISO 8601 output is, by their own admission, broken: https://www.postgresql.org/docs/12/datatype-datetime.html#DA...
> Almost everything should be capable of parsing and outputting ISO 8601 dates [1] today.
Why is it so hard to configure a Linux system (its locale settings) to get RFC 3339 formatted dates everywhere? Sure, I can `ls -l --time-style=full-iso`, `git log --date=iso`, `date --iso-8601=s`, `date --rfc-3339=s` and change the configuration of every single application by hand. Am I missing something?
Often, people recommend the hackish `LC_TIME=en_DK.UTF-8`. This however, doesn't work for Java applications and caused various other issues.
I don't think it's actually that important that every language deals with them the exact same way. I interpret that to mean they all translate the APIs as literally as possible between them, using the same method names, same types of arguments, etc. Different languages all have their own quirks and patterns and it's also useful that the library be idiomatic within the language.
Most of the problems I have seen in dealing with time, across various languages, arise from allowing types to be way too ambiguous. A lot of code uses interchangeably things like "UTC -0700" and "America/Los_Angeles" which are actually very different (one incorporates daylight savings and one doesn't). The important fix is that languages start using reasonable abstractions and are stricter about requiring explicit conversions between types rather than trying to implicitly guess an interpretation.
The first library I've seen get this right was Joda in Java, and it later got included into the standard library for Java. It's been copied other languages, and I've used it on the frontend a bit as JSJoda, but the literal translation makes it a bit awkward in JS and I found it was hard to get other JS developers to prefer it over the more popular moment or date-fns. Temporal looks great, it actually seems to borrow heavily from Joda but doesn't literally copy all of the names or methods so hopefully it will be the best of both worlds.
It's not just that. Timezones are the real bugger. Microsoft has their own list of names separate from the standard IANA timezones, for example. If it weren't for timezones, IMO dates are pretty damn trivial. It's just a matter of storing and transferring them properly (in UTC, always!)
Three days and an hour more than you think, because it's the weekend, and an extra day because the public holiday for tomorrow may or not be a working day. Oh and there was a timezone change.
Even before the rollover it get's bad. I had a CI failure on 31 December 2018 for code which worked fine on 31 December 2017, because it was the first time for that code to have Dec 31 in week 1 of the next year.
And last year someone else's code failed on 30 December 2019, so I had a pretty good idea where to look.
Still need to fix a bug in code written only yesteryear because the 1st of July wasn't on a Monday this year, but I decided to snooze that test failure ... it'll work fine again in 9 years.
About your question it’s impossible to answer without further context.
There may be DST tonight, or a leap second, or the enforcement of some strange treaty that will change the time zone..
This is a case for events! The store opens when the owner unlocks the door..... but since you are in that nebulous time when it is "closed" the next "open" may never happen.. so maybe what really needs to happen is a giant disclaimer around times for things...
like in your search results for let's say some M-F 8-5 business... it would say "Hours: 8:00-17:00, Closed right now, in 72% of the cases, the next opening time is tomorrow morning at 8"
I recently did this for a task scheduler. The logic lives in SQL. That was a "fun" query to write... You might think it's the wrong tool for the job, but it was a lot faster than reading every possible row and checking it in the application itself.
There is a case to not store a time in UTC: you schedule a meeting in the future and the local authorities change when they start DST in that location. Now your user gets the alert an hour too early or late for their meeting. The scenario is more fleshed out in the link below but I don't want to just copy and paste the article into the comment.
I can't speak for every language you listed, but C# has great and clear datetime builtin.
Probably the only thing perhaps not the most standard are the names they use for actual time zones? So perhaps that could be improved.
But seriously I don't know how the fuck javascript people can work with dates. It's ATROCIOUS. I think my favorite one is 0 indexes on months? like if you do date(2020,07,09).. is that July 9th 2020? nope, fucking June! Not June 8th.. but June 9th.
I don't know what monster did that but there should be a special place in coding hell for him/her!
I believe that the logic behind 0 based months in many languages that use them, although I don’t know if this is true for JavaScript, is that month numbers are often used as an index into a table of month names so numbering months from 0 is convenient.
Well sure, I get the reason behind.. but the reality is it's just a horrible convention, especially when you pass multiple inputs (year, month, day, hour, minute, second) and "month" is based on 0 index but the rest are not.
> I can't speak for every language you listed, but C# has great and clear datetime builtin.
If you think built-in .NET DateTime is any good, give NodaTime a try. Standard DateTime is barely usable, compared to it.
For JavaScript, there is excellent js-joda library (same design as NodaTime and Joda-Time), but it's 43 kB minified and compressed, which is... not terrible but also not great, really depends on your use case if it's worth it.
>For JavaScript, there is excellent js-joda library
Well that was kind of my point- needing an external library to manage datetime is ludicrous. That's why I'm talking about what C# has builtin. No matter what new project you start, whoevers code you are working in- you can just use builtin.
>give NodaTime a try. Standard DateTime is barely usable, compared to it.
Went to the website to see some example code.. looks basically the same? Anyway thanks for the heads up but I work with datetime stuff constantly and I am not missing anything. It's easy to create datetimes, convert between time zones, add timespans etc.
> Went to the website to see some example code.. looks basically the same?
The main difference is that there are separate types for the following concepts:
1) A point in time in global timeline
2) A specific date and time in specific time zone
3) Specific date and time but without any information about time zone (and two more related types that contain only date information or only time information).
There are a few more types, but these illustrate the main difference from .NET DateTime. In case you missed it, the basic concepts are explained here: https://nodatime.org/3.0.x/userguide/concepts (which I should have linked to in the first place).
Your proposal might seem crazy, but we've actually been able to do this before. While learning WebXR not long ago and looking for examples, I discovered it was based on OpenXR (1) and literally every big tech company has APIs that were similar - I ended up reading docs and sample code from Android, C#, and even Apple to get a better idea of how things were wired together. It was a very pleasant surprise!!
So much this. Not to mention that even within the same language, the implementation can differ (e.g. Firefox vs Chrome).
I recently had to parse a bunch of dates in python, writing them to postgres, and then handle the same dates in javascript. And boy was it a PITA. The worst problem was the handling of "BC" dates. I had to hack my way around the boundary between python and sql. Javascript is no better, it simply doesn't compute BC dates without heavy hackery.
I agree in principle, but achieving that kind of harmony between languages is analogous to the world‘s governments agreeing to “save succeeding generations from the scourge of war”. That sounds like an exaggeration, but even if language maintainers are all enlightened enough to compromise, the communities are not necessarily going to comply. The minute a language changes how it deals with dates and times, it’s more than likely someone will, very loudly, announce their intent to fork it in order to preserve the old way of doing things.
Maybe I’m stating the obvious here, but there is actually a standard: ISO 8601. Vendors however don’t seem to follow this, either consistently or at all. As for a standard library, Javascript doesn’t have one - everything is built into the core language. Also, fundamental differences between language syntaxes could have a huge impact on usage and implementation. So even if every existing and future language on the planet followed ISO 8601, there would always be that language barrier.
ISO8601 is a representation standard, not a standard for abstract concepts.
https://news.ycombinator.com/item?id=23783603 called for Unicode but for Time, which I think is perfect. In that framing, ISO8601 is UTF-8, but it is Unicode that is needed for everyone to agree on what is "code point" and what is a "character" (equivalently, what is a "calendar date", what is an "absolute timestamp", etc).
I don't expect that the usage and implementation would be the same in all languages. Just that they would at a high level have the same representations and provide the same operations.
For example, if the standard was that a datetime would be represented as separate year, month, day, hour, minute, second, time zone some languages might implement that as a struct with names fields for each of those 7 elements.
Some languages might implement it as an object with properties for each of those elements.
Some might implement it as an array with one entry for each of those elements.
If the standard called for a function add_seconds that adds a given number of seconds to a datetime, modifying that datetime in place, languages that use a datetime struct might provide a standalone function that takes a pointer to a datetime struct and the number of seconds to add.
Languages that represent datetime as an object might have add_seconds as a member function.
So if I'm a Perl programmer and know how this standard works in Perl that would not necessarily mean it is obvious to me how it works in Python or C. But it would mean I could think about time the same way in all of them. I could expect to have corresponding data structures in all of them, with the same core set of operations available in all of them.
Names might be slightly different (e.g., what the standard calls add_seconds might become addSeconds in a language that by convention uses camel case for member function names), but the point is what these functions and data structures actually do would be standardized so once I know how to do all my date and time stuff following this standard it is easy to map that to the language specific implementations in JavaScript, Java, PHP, C, and the rest.
I'm not sure strings are easier. When to use mutable vs. immutable strings has a significant performance impact, how do you manage memory for them (including when do you copy strings vs work with a slice) are all questions where there's at least 3-4 distinct designs that you might want (a C like language, a C++-like language, a Rust-like language, and a GC'd language).
In contrast, for dates and times, everyone really could have used the same design. Maybe you'd need a slightly different design for dynamic languages, but I'm not even sure about that.
There’s a history of using local Martian solar time in the past, driven by the need to operate in the Martian daytime for rover safety. They even made special watches that ran “slow” compared to earth times so that they kept correct Martian solar time for some of the missions.
However for “absolute” chronological records you would be looking at using Barycentric Coordinate Time, which is what we get when we do a bunch of corrections to subtract the effects of the sun and earth’s (and the other planets) mass and motion, leaving us with a virtual “clock” that is suitably common for anything in the solar system.
To quote one definition of Barycentric Coordinate Time - ”It is equivalent to the proper time experienced by a clock at rest in a coordinate frame co-moving with the barycentre of the Solar System: that is, a clock that performs exactly the same movements as the Solar system but is outside the system’s gravity well.”
The ELI5 I normally use is roughly: It’s what we get if we take the Solar System in its normal orbit around the Milky Way, with some fancy magic we subtract away all the stuff, sun, planets, moons and all the asteroids and comets we can count, and then with a little more fancy magic, we put a super accurate clock that doesn’t weigh anything at all back at the center of where all the solar system stuff used to be.”
1) Latitude on another planet is straightforward: take the rotational equator, divide into 90 degrees north and south, done. But what about Longitude? Here on Earth, the prime meridian is Greenwich, because reasons. On Mars, it's indexed to a certain crater. But on the gas giants? Yeah, we still don't have a good plan about that.
2) Paul Krugman's thesis (yes, that Paul Krugman) is on relativistic economies. As in, my planet is in a deep gravity well, your's isn't. My clocks pas a lot slower. Now, how do I calculate interest? What about letters of credit for ships traveling between places to ship goods? His conclusion: let's hope there isn't money by then, because interest can't work between relativistic time frames.
In reality: Even if in a few hundred years we have the capability to travel at FTL to other solar systems, we will still be using GMT as "ship's time".
Sorry for not being clearer. By "JavaScript people", "Java People", etc., I didn't mean the communities. I meant the people who make the standards for those languages.
This basically exists, and it's called ISO 8601. But the scope of ISO 8601 isn't programming languages and APIs, but data models and their representations. A subset of ISO 8601 forms the basis of RFC 3339. Official copies of ISO 8601 are available for a fee from ISO. For the purposes of this discussion thread, consult this file hosted by the US Library of Congress for reference [1].
ISO 8601 defines a number of terms of art to represent a thorough mental model of the problem space, and then goes on to define string representations on how to express them. But it's paywalled, so people reach for RFC 3339 and the Wikipedia article instead. These focus on representations, and the definition of the concepts isn't captured clearly, so sometimes they're rediscovered independently. Other times, they're not.
Serious attempts to figure this out usually coalesce to something that looks and behaves like Java 8 time. Java 8 time may be verbose, but its concepts are clearly mapped out, and the API bears some marks of a misuse-resistant design. Compared to that, there's efforts like the standard libs for Python, Ruby, Go, or most third-party libs for JS, Rust, that don't bring clarity to the table, and don't present any solution for dealing with calendrical or clock-face objects, and do little to discourage misuse of their point-in-time objects in abstract contexts.
This proposal falls much, much closer to the Java 8 way than to the "everything is an instant, go make your own classes" way.
One shortcoming of ISO 8601 is that it has no provisions for abstract timezones. Instead, people go outside of the standard to represent ISO datetimes alongside IANA timezones.
But the most glaring problem with ISO 8601 is that it doesn't define partials where a more-significant term is unknown or missing: there's no valid, unambiguous way to refer to the 15th day of March, while leaving the year deliberately unspecified. This means that anniversary dates (e.g birthdays, holidays) aren't possible to represent in the abstract.
Likewise, there's no valid, unambiguous way to refer to the 29th second of the fourth minute of every hour. This is much less important than the birthday shortcoming.
The Library of Congress has a standard which extends ISO 8601 with a number of useful constructs for their purposes [2], like uncertainty qualifiers, but even that standard has no mechanism to represent a month+day partial in the abstract.
> The 2000 [of ISO 8601] version allowed writing "--04-05" to mean "April 5" but the 2004 version does not allow omitting the year when a month is present.
Then all of them should implement that in their standard library, so that going forward we've got one sane conceptual time handling system everywhere.
I tire of dealing with the quirks of everyone having their own approach.