Probably just one of those hard problems which looks easy from the outside. Nobody wants to handle that thankless mess, which is guaranteed to be broken on any of a hundred edge cases.
I understood it to be because the TZ library changes frequently enough that it should be an external package. Date math shouldn’t change based on the language version you’re using, nor should you have to upgrade the language when Arizona finds a new way to creatively alter time.
I think that'd be the worst place to take it from for the same reason. If I build a package using today's current TZ database and it works on my machine, it shouldn't stop working if I share it with someone using an old CentOS from several years ago.
True, but it’s generally a lot easier to patch software than expect someone to update their whole OS.
(Generally. I know plenty of shops deployed Exchange in 2009 and it still works so why fix it, goshdarnit! Those people aren’t generally updating their OS either though.)
The zone database adds more historic entries than they do modern ones. You can; however, calculate the correct 1942 "summer war time" in the british isles if you're so inclined. The tendency to do this while also copying copyrighted text into the file shows that the zone maintainers are not interested in the same problems most users are.
The TZ database is a complete mess. The whole thing should be replaced with a '.timezone' TLD, each civil time keeping authority should get control over it, and TXT records used to publish current TZ information. OS Vendors can cache all that in the OS if they like, but this secondary central time authority has outlived it's usefulness.
It’s stage 3, and they offer production-ready polyfills. For a project I work on, that’s a reasonable enough approximation of “ready”. Your project needs may vary. But it should be stable enough to use now with a userland implementation if the API is what you’re after.
I think this might be one of those “difficulty curve” memes. On the left, the Padawan: “just use UTC timestamps”. In the center, the journeyman: “no!!! we have to store time zones and translate between them! Time zone awareness!” On the right, the Jedi master: “just use UTC timestamps”.
Yes that works for most use cases but there are use cases where you may need to store or shuttle the time zone. For instance you want to know this UTC timestamp was originally created in PDT. You would have to store two variables. Most other languages have this functionality it can be useful and is good to have, probably only needed by Jedi’s too.
I have always wondered why breaking the timestamp (in UTC) and the timezone into two separate data points and storing both is not the accepted solution. It appears like the cleanest solution to me.
From my experience, it certainly is. Easy to tell time in sequence as well as local time then. When daylight savings hits you can still calculate well, and can quickly get real time for hours worked out drive time for freight across time zones to follow the hours of service rules.
Two different implementations might make two different local times out of that, e.g. due to not being aware of changing DST/timezone policies. Hence the recommendation of separating between user/clock/calendar time (which must be exact to a human) and absolute/relative timestamps (which must be exact to a computer).
You can't accurately convert future local times to UTC timestamps yet, as that conversion changes when timezones change.
Let's say we schedule a meeting for next year at 15:00 local time in SF. You store that as an UTC timestamp of 2025-08-24 22:00 and America/Los_Angeles timezone. Now, imagine California decides to abolish daylight savings time and stay on UTC-8 next year. Our meeting time, agreed upon in local time, is now actually for 23:00 UTC.
Wow thanks for sharing this, this certainly is a use case not covered by the system I proposed. I imagine this will require versioning of the timezone so we can translate our America/Los_Angeles v1.0 timestamp to America/Los_Angeles v2.0.
The article gives an example, of you buying a coffee with your credit card while travelling to Sydney, and returning to Madrid, and a few months later seeing a charge for 3:50 AM on that date...
Google Photos also get confused with "When was this picture taken?", my older model camera just stores the EXIF date in "local time" and I have to remember to change its timezone when travelling, and if GPhotos can't figure it out, it might show pictures out of the airplane window, and then the next series of pictures are from the departure airport because they're from a "later" hour (since it's missing the timezone info).
I suppose I could keep it at my home time or UTC...
That is how I would expect a bank statement to read though. I would find it infinitely more confusing if I bought something online in my bank showed the time of wherever the seller was located.
The photos problem is harder, but the app needs to just convert it from local time to UTC when you import it. There's not much that can be done if you take photos on a camera with a different time zone than you're in without more metadata.
You'll find that most bank systems avoid any notion of time precision higher than calendar days for a variety of reasons :) As a side effect, this practice conveniently avoids that problem entirely.
> That is how I would expect a bank statement to read though. I would find it infinitely more confusing if I bought something online in my bank showed the time of wherever the seller was located.
When using my banking app abroad (one that does show timestamps), I'm usually much more confused by their presence than by their absence.
> The photos problem is harder, but the app needs to just convert it from local time to UTC when you import it.
But I usually want to see the time in local hours and minutes for photos! Sunsets, new year's fireworks etc. happen according to local time, not UTC or my current timezone's offset.
Exif (fun exercise: find out who specifies it and when it was last updated!) actually didn't even have a way of storing timestamps in UTC or with zone information until fairly recently: It was all local times without zone information.
I've seen some software work around that by combining the local date/time with an embedded GPS tag, if present, which does contain the time in UTC.
Ironically, time zones are a hack with bad precision about the position of the sun in the sky. The GPS coordinate side steps the nonsense (can be converted to the time zone as defined in that place at that moment).
While UTC timestamps look like they solve all of the problems in one passing, they have plenty of edge cases that can blow up spectacularly. A good example of this is daylight saving time and countries changing their rules around it. You would think this is a rare occurrence, but it actually happens pretty often [0]! In the last ten years, fourteen countries have abolished daylight saving time.
Technically you could use TAI for most things internally and use an offset when you display. It works perfectly for records. The only issue is with scheduled things when your users probably want to point at something in their timezone.
The main problem is that future values of TAI converted into most time zones is nondeterministic. On the other hand, at least you can guarantee all TAI seconds will actually occur.
Or toLocalDisplayString(TAI timestamp). It seems like timezones and their rules change over time and geographic location, using todays rules to show dates back in time with previous rules would be broken right?
Well, any correct time handling library will use something like the IANA timezone database (aka tz/tzdb/zoneinfo) which stores all the changes in timezone rules for localities over the years - a library that only knows "today's rules" would be fundamentally broken as you say. So the internals of toLocalDisplayString(timestamp, timezone, calendar, locale) should look up the appropriate rules in effect at the timestamp and use those to decide the local time to display.
We hit this with the US timezone change in 2005. The front-end devs were using moment.js which didn't know about the previous start/end dates.
These days I try to encode everything that is logically a date as yyyy-mm-dd. And if I need to do math with it, I often work with an offset julian date as an integer. But that only works if you stay on this side of September 1752:
% cal 09 1752
September 1752
Su Mo Tu We Th Fr Sa
1 2 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Before roughly 100 years ago, calendar dates were region-dependent anyway (Russia was still on the Julian calendar until 1918), and time zones didn’t really exist until roughly 150 years ago (their establishment mostly being motivated by the spreading of railways). It’s okay to apply the perpetual Gregorian calendar both into the past and the future by default. It probably won’t last more than a couple thousand years into the future as well, considering Earth’s decelerating rotation.
The solar day varies in length by more than a minute over the year. That doesn't correspond to a well-defined time zone. Also, "zone" implies a geographical area, which meridians arguably aren't.
The mapping from year, month, day that I use (based on the Wikipedia page, but starting on march 1, 1600) doesn't take that gap into account. So the days in that gap exist for me, but we don't deal with dates that far back.
Sure, but now you've reduced the scope of the problem to a few edge cases. Every other solution I've seen still has these edge cases and doesn't solve the core problem as simply as UTC. If you think otherwise, can you describe or provide a link to these other solutions?
For region-specific events (which includes most physical meetings, by convention many financial processes etc.), it's much safer to store both the local time and time zone city, as well as the UTC offset at the time of writing, and to convert to UTC only at runtime using an up-to-date time zone database.
That way, you can identify all of:
- Future timestamps you might want to re-process, e.g. for notification scheduling, because the future UTC conversion has changed between scheduling/updating the event and now.
- Equivalently, timestamps written by software/an OS running an outdated TZ database. You should talk to them; things are about to go wrong if the date is in the non-too-far future!
- Trivially and without conversion, the local time that people will use in the meeting notes, documenting that you missed the meeting because you didn't update your TZ database and dialed in to the meeting an hour late
Like, what if you only need the date but not the time? You can use timestamp to store a birthday, but which in which timezone should you transform it back to date?
Or what if it is specifically about time in timezone independent way? You want to wake up ate 06:00 no matter in any timezone. Just something like alert.
You could use part of ISO8601 like 2020-02-02 or 06:00:00 to store exactly what you specify. But with timestamp, not so much.
I’ve been thinking about this; does a timestamp even work, then, without not only a time zone, but a location? I mean time zones are poor man’s locations, but if we want to do this properly…
No - the master's answer is that you use one or the other depending on whether you are representing absolute time or clock/calendar time. The expertise lies in understanding the difference between those two things, which one your use case falls into, and how to ensure other developers and the very APIs provided by your platform do not make silent assumptions about that decision.
Often it feels like you can "just use UTC" because it's hard to imagine the fail states, and APIs often make tz assumptions for you so you may never notice those fail states (occasionally your software will just be buggy and annoy a user, decreasing the feeling of quality and trust - it may never result in a disaster).
And even then it's difficult. Time zone definitions change. Summer time does not start and end on the same date everywhere. So you also might need to know the UTC offset corresponding to the time zone at that time not just the UTC offset of that time zone today (assuming it still exists)
Edit to add: still, this sounds like a great improvement. A common mistake that naive programmers make is to believe that they can hand-roll their own date/time functions. And JavaScript sort of forces them to do that.
It’s not difficult if you understand what you are trying to do conceptually.
For example, if you are trying to say “run this task at this specific time in Los Angeles time” and you put a specific UTC offset, it just doesn’t make any sense. Los Angeles time consists of two offsets, and yet here you openly put down something wrong. You need to put into your system literally Los Angeles time (like America/Los_Angeles) because that’s what you want. You didn’t want an offset. Dear god why are you putting an offset then?
Or you want to define a specific date but then you put into your system a date with a time like 12/12/2024 00:00. Like you started off with “I want to define a specific date” and here you openly just put a time. You had to make up 00:00. Why are you just doing random things without thinking?
I wasn't literally suggesting that you store offsets. Or timestamps. There are way too many weird cases around doing that. But "America/Los_Angeles" is a reference to a file in tzfile(5) format, which contains, among other things, the UTC offset. And a function that produces the correct date and time in Los Angeles at any point in the past has to know (among other things) if that offset was ever anything different, and if it was, when it changed. And many other things.
There are date/time libraries that can't get all of this right, but you'll come a lot closer using them than you will rolling your own.
Don't store raw timestamps. Don't store offsets. Use date/time data types.
Dates of past events are always UTC, dates of future physical events must always be a timestamp and a location, dates of future virtual events are either UTC or location based depending on how virtual they actually are.
I can tell you from bitter experience that if you have an event where a person has to arrive at a place at a time and you store that as UTC instead of wall clock, you will have a problem at some point
Past/future doesn't matter, what matters is context. You don't need to use timezones for ie. setTimeout even though it refers to the future and you should have timezone available for past events ie. atm withdrawal.
setTimeout takes a duration in ms, not a timestamp. If it did take a timestamp, I think you would need to pass it a timezone to disambiguate.
Maybe a better argument is, “when you’re setting a phone alarm, you don’t tell it a timezone.” Maybe the distinction is whether the timezone is established at write time or read time.
Scheduling on a calendar (occur on date X, time Y, in zone Z) and scheduling based on timedelta from instant time (occur exactly X milliseconds before or after instant Y) are both valid, and you can do timedelta scheduling in UTC without needing timezones. The issues come from conflating the two; using timedelta reasoning for calendar scheduling, or using calendar scheduling when you want an exact timedelta.
> when you’re setting a phone alarm, you don’t tell it a timezone.
Which coincidentally and ironically makes phone alarms surprisingly difficult to implement in a way that does not break in the face of DST shifts, timezone changes etc., as Apple has learned the hard way a couple of times.
Past/future does matter, as generally speaking it's possible to accurately convert between local time and UTC for times in the past, but not in the future.
There's a few exceptions where governments have retroactively changed timezones or DST rules, but at that point you've lost anyway.
Yes! All past events have well defined times, even in the face of human silliness like changing timezones and before such ideas existed.
The future is defined by intent which is imprecise (will Oregon drop daylight savings time or not — who knows?). I don’t know how many seconds it is until my next birthday, but I know exactly how many have passed since I was born.
Presumably this new API will fix the fact that JS does in fact know about some time zones, but not most.
Shield your eyes from this monstrosity that will successfully parse some dates using `new Date(<string>)` in some select special time zones, but assume UTC in the other cases:
It's more about the javascript spec. If the spec says "thou shalt support this and that" and one of the browsers implements more than that, we are now back in the 2000s where one browser may be supported by some websites but others aren't.
Canvas by Instructure, one of the largest LMS (learning management system) in the world officially supports all major browsers.
Unofficially schools tell students to use Chrome because some tasks fail often outside of Chrome. In particular Safari's default settings for cookies/privacy often causes the system to fail - particularly with integrations that use iframes/popups and other antiquated tricks.
I'm actually less surprised about this in 2024 than I would have been for a webapp in 2014.
I feel like we peaked somewhere around the mid 2010s with regards to application compatibility: No more Flash, but also more than just 1.5 rendering engines.
Before that, it was all "oh, sorry, Windows .exe only"; since then, "sorry, Chrome visitors only".
It was nice. As long as you weren't doing something totally inadvisable like using IE 7 or something, things generally worked fine. Blink, Gecko, WebKit, whatever. Even random tiny FOSS browser projects wrapping somewhat outdated builds of WebKit or Gecko worked ok the majority of the time as long as you spoofed the user agent string of one of the big guys.
People put serious effort into even IE compat for a while. AFAICT the beginning of the end came with trying to do battle with mobile browsers; you simply couldn’t debug all the potential problems well enough. I remember burning a month on a regression that affected only iOS before Apple fixed it. Of course people were going to eventually pick an easy standards based target and tell everyone else to pray.
After using Canvas for 2 years, I haven't had any problems with Firefox (except for the Lockdown Browser feature our school used to require, which I think is being gradually phased out).
I don't think this is correct. I think the JavaScript spec here defines a string format which is extremely narrow, but then leaves it open to browsers implementing whatever they want.
> The function first attempts to parse the format of the String according to the rules called out in Date Time String Format (15.9.1.15). If the String does not conform to that format the function may fall back to any implementation-specific heuristics or implementation-specific date formats.
> ECMAScript defines a string interchange format for date-times based upon a simplification of the ISO 8601 Extended Format. The format is as follows: YYYY-MM-DDTHH:mm:ss.sssZ
> Z is the time zone offset specified as “Z” (for UTC) or either “+” or “-” followed by a time expression HH:mm
> Note2: There exists no international standard that specifies abbreviations for civil time zones like CET, EST, etc. and sometimes the same abbreviation is even used for two very different time zones. For this reason, ISO 8601 and this format specifies numeric representations of date and time.
The hint as to what is going on then comes from MDN, which more documents the ground truth than the goal.
> There are many ways to format a date as a string. The JavaScript specification only specifies one format to be universally supported: the date time string format, a simplification of the ISO 8601 calendar date extended format. The format is as follows: YYYY-MM-DDTHH:mm:ss.sssZ
> Note: You are encouraged to make sure your input conforms to the date time string format above for maximum compatibility, because support for other formats is not guaranteed. However, there are some formats that are supported in all major implementations — like RFC 2822 format — in which case their usage can be acceptable. Always conduct cross-browser tests to ensure your code works in all target browsers. A library can help if many different formats are to be accommodated.
That table then comes from RFC2822, which also doesn't want you to use string named time zones, but as RFC822 has such it needs to still support it a bit--I imagine this probably came from back when this was used by ARPA-- and so has a section on "obsolete" date and time format extensions, which only explicitly requires support for US time zones and (notably) military formats.
Honestly, it sounds like the most reasonable behavior here would be to _only_ support "Z" (optionally with "+<offset>") and none of the 3-letter codes. Unfortunately it would probably a breaking change to remove support for the existing codes, so it wouldn't happen.
Just to note, that table is from the "Obsolete Date and Time" section. AFAIK, RFC 2822 only really allows the number offsets and Z.
Anyway, yeah, that does explain the situation we are in. And yeah, it looks like if you are extremely literal-minded and insist on supporting obsolete notations on your new thing, that would make your code be exactly like the one the OP pointed.
It's a bad decision all around, because the RFC 2822 isn't concerned about general purpose time handling. A programing language shouldn't use something like this.
I also came down to say the same thing -- Joda's library was the best library to deal with date & time
( Now with all the changes copied to the standard library, I haven't used that library in years )
IMO, the pattern that Joda popularised is the most robust option for managing dates we've seen so far. If I'm evaluating date/time libraries in a language I'm not used to, ones that looks like their authors have looked at and understood the API of Joda or derivatives are going to be strong leaders.
Having a good datetime standard is half the battle. The other (more difficult) half is getting broad adoption for it. If it was just a matter of computing within the bounds of my application then there are a bunch of great libraries that make this stuff easy already. However now the question is - if I pass an encoded ZonedDateTime object from my browser/server to a third party, will it be able to interpret it? Realistically I'm just going to convert it down to an ISO string or unix TS as always just to be safe, thus going back to the exact same problem.
Temporal is getting standardized by the IETF so you can expect it will eventually have broad ecosystem support beyond Javascript, here is the RFC https://www.rfc-editor.org/rfc/rfc9557.html
If you drop the time zone, then you lose essential context that the consumer won't have unless you encode the time zone out of band. And no, an offset is not a time zone.
The answer to this is RFC 9557, which was recently published. Rust's Jiff library (of which I am the author) supports it. And I believe java.time supports it. Otherwise, yes, adoption will take time. But it's the right way forward I think.
> In other words, the function responsible for transforming a timestamp into a human-readable date is not injective, as each element of the set of timestamps corresponds to more than one element of the "human dates" set.
The author confuses the concept of injectivity and well-definedness. For an injective function f, it has to be true that given distinct a and b, f(a) != f(b). That's not the problem here; rather the problem is that for a timestamp t there's no unique human-readable date x such that f(t) = x. That's well-definedness, not injectivity.
You could talk about the inverse function, from human-readable dates to timestamps, and correctly point out that that function is not injective, because more than one human-readable date maps to the same timestamp...
The ability to convert it to any human-readable time is actually the problem: without additional information you don't know which one to pick, and are forced to make certain assumptions, such as using the user's local time zone or defaulting to UTC. That's the point of the section of the article I quoted above.
For example, given just a timestamp, you don't even know what day it was. Was the user in New York? That 3:50am was actually 11:50pm on March 15th.
I genuinely still don't get it, but why do you need to fix the reference point once and for all?
I would assume in 99% of cases the user is simply just interested in his local time anyway.
If you really need the location info, then you would obv have to make some other tradeoffs like either
1) always store the location alongside the timestamp or
2) complicate (probably massively so) the time format, storing and parsing/processing logic
But I don't see how that's an issue of UTC timestamps per se rather than being an issue of requiring more information than just time (i.e. time AND location at the time).
Again, really would appreciate an explanation of where I am mistaken here because thus far the whole point of OP seems like a trivial non-issue to me.
Anything for maybe the last hour or I can see; "1 day and 5 hours ago" and making me hover over the string (and pray that there's an alt text available that I still can't copy-paste) is very annoying.
I really wish, space permitting, web designers would start at least including the actual timestamp in the regular/non-alt text as well, at the very least for professional tools if not for social media sites.
One time it works is when your team is across many time zones, the data being listed spans many time zones, and what’s important is knowing the recent events from older ones. And yes, also showing the absolute UTC stamps too
agreed the format parser is stupid, but thats more a cosmetic issue. its had the ability to create location aware dates since the first version 12 years ago
I think they mean splitting the "Number" [0] type into an integer type and a decimal type.
Currently the "Number" type is used for every number and it gets stored as a double, and can "only" represent "integers" safely in the range of ±(2^53 -1).
Though there is a "BigInt" [1] type.
* Integer types of various sizes (for efficiency) and so you don't have to constantly do floating point comparisons (i.e. equal within a small delta) and generally have better compatibility with other languages.
* Decimal floating point type so you can work in base-10 and don't have rounding issues.
Plus all of the error checking you get for free if you're using typescript instead of raw-dogging it with plain javascript or coffee-script :-)
Temporal will be really nice in that it supports remote time zones, allows you to iterate through daylight saving transitions, etc.
I can't wait for it to be fully taken advantage of by things such as mui's date time picker. Imagine if after selecting the fall back day, it saw the transition and let you pick a time during the extra hour. If after selecting the spring forward day, it wouldn't let you pick a time during the hour that doesn't exist. Today that doesn't work because everyone uses different crappy third-party libraries and mui functions on top of a lowest-common adapter that certainly doesn't do stuff like "show me the DST transitions in this day".
This stuff matters sometimes; a user of my NVR wanted to save a clip during the fall back hour and got the wrong result because these things just don't work right today. https://github.com/scottlamb/moonfire-nvr/issues/244
"Let's consider an example: suppose I want to record the moment I make a payment with my card. Many people might be tempted to do something like this:
const paymentDate = new Date('2024-07-20T10:30:00');".
What? I don't think anybody would define a date like this to record some moment. Most developers would simply use new Date() without any parameters, thereby creating a timezone-safe absolute underlying timestamp value. This value then is of course stringified relative to the timezone of the caller when retrieving it, but that's expected.
The new Temporal api might be nice but it doesn't need flawed examples to make its case.
> The Temporal API represents a revolutionary shift in how time is handled in JavaScript, making it one of the few languages that address this issue comprehensively.
Note that there's also a Rust datetime crate, jiff, that's inspired by the Temporal API and features zone-aware datetimes (from burntsushi, author of ripgrep and Rust's regex library): https://crates.io/crates/jiff
Whats your source for it not being available in browsers/node until 2028? Update cycles are pretty quick these days for browsers and mozilla/safari has been pretty good to add APIs that don't increase attack/privacy/interface surface.
Still don’t get it. Is it to be able to show the user a local time for the timestamp? If that is a requirement , why not just also store the timezone along with the utc timestamp? Should the date-object really know this?
The problem is that the result of toUTCTimestamp(datetime: January 1st 2077 1:15am, timezone: New York) may be X today, but timezone rules could change soon, and then it becomes Y tomorrow. If you've only persisted (unixTime: X, timezone: New York) in the database and you try to turn X back into a local time, maybe now you get December 31, 11:45pm. If you're a calendar application or storing future times for human events, people will think your software is broken and buggy when this happens, and they will miss events.
Good, I also used to think storing timestamps in UTC was sufficient. The examples really explained the problems with that well. One other issue to note is that, if you store dates in UTC, now the fact that they are in UTC is a tacit assumption, probably not recorded anywhere except in organizational memory.
So the new API will be a very welcome addition to the JS standard library.
However, and this is probably a bit off-topic, why are the ECMAScript guys not also addressing the fundamental reasons why JS continues to be somewhat a joke of a language?
- Where are decimals, to avoid things like `parseInt(0.00000051) === 5`?
- Why are inbuilt globals allowed to be modified? The other day a 3rd-party lib I was using modified the global String class, and hence when I attempted to extend it with some new methods, it clashed with that modification, and it took me and hour or two to figure out (in TS, no less).
- Why can't we have basic types? Error/null handling are still haphazard things. Shouldn't Result and Maybe types be a good start towards addressing those?
Because that was the original behavior, and you can't just change that behaviour, or half of the web will break (including that 3rd party lib and every web site depending on it)
> Why can't we have basic types? ... Shouldn't Result and Maybe types
Neither Result nor Error are basic types. They are complex types with specific semantics that the entire language needs to be aware of.
So clean the language up, call it a slightly different name if you want, and let those who want to go modern do so. For those who can't, offer maintenance but no major new features for the original version.
Being wedded to mistakes made in the past for fear of breaking current usage is the root of all programming language evil.
Being able to modify built-in types is extremely useful in practice. This allows you to backport/"polyfill" newer features, like for example improvements to Intl or Temporal to older runtimes. If all the built-in types were locked down, we'd end up using those built-in types less because we'd more frequently need to use userspace libraries for the same things.
Like, you are asking for a Result type. If this was added to the spec tomorrow and existing objects were updated with new methods that return Result, and you can't modify built-in types, then you can't actually use the shiny new feature for years.
On the specific point of Maybe type, I think it's not very useful for a dynamically typed language like JS to have "maybe". If there's no compiler to check method calls, it's just as broken to accidentally call `someVar.doThingy()` when `someVar` is null (classic null pointer error) versus call `someVar.doThingy()` when someVar is Some<Stuff> or None, in either case it's "method doThingy does not exist on type Some<...>" or "method doThingy does not exist on type None".
> Like, you are asking for a Result type. If this was added to the spec tomorrow and existing objects were updated with new methods that return Result, and you can't modify built-in types, then you can't actually use the shiny new feature for years.
And that's a good thing, because you know that with a specific version of JS, the inbuilts are fixed; no mucking around to know what exactly you have, and no global conflicts. I find it surprising that you would defend this insane state of affairs. If you have worked on really large JS projects, you would see my point immediately.
It is like saying the immutability of functional programming is a bad thing because it limits you. The immutability is the point. it protects you from entire classes or errors and confusion.
> If all the built-in types were locked down, we'd end up using those built-in types less because we'd more frequently need to use userspace libraries for the same things.
The same reason you couldn't in 1996: because the assumed entry point for the language is someone who can barely conceptually manage HTML; doesn't want to have to deal mentally with the fact that numbers and text are fundamentally different kinds of thing; and - most importantly - absolutely will not accept the page failing to render correctly, or the user being shown an error message from the browser, for any reason that the browser could even vaguely plausibly patch around (just like how the browser has to guess whether an unescaped random stray < is just an unescaped less-than symbol or the start of an unclosed tag, or guess where the ends of unclosed tags should be, or do something sensible about constructs like <foo><bar></foo></bar>, or....)
> - Where are decimals, to avoid things like `parseInt(0.00000051) === 5`?
I personally dislike decimals, I would prefer a full BigRational that is stored as a ratio of two BigInts (or as a continued fraction with BigInts coefficients.
Decimals solve the 0.1+0.1+0.1!=0.3 error but are still broken under division.
The Java team didn't initiate the process of making it an
Internet Engineering Task Force standard; whereas this team did. Even though this is JavaScript centered, it really represents a much broader effort, that should help interoperability between languages and across online systems.
284 comments
[ 4.5 ms ] story [ 271 ms ] thread(Generally. I know plenty of shops deployed Exchange in 2009 and it still works so why fix it, goshdarnit! Those people aren’t generally updating their OS either though.)
The zone database adds more historic entries than they do modern ones. You can; however, calculate the correct 1942 "summer war time" in the british isles if you're so inclined. The tendency to do this while also copying copyrighted text into the file shows that the zone maintainers are not interested in the same problems most users are.
The TZ database is a complete mess. The whole thing should be replaced with a '.timezone' TLD, each civil time keeping authority should get control over it, and TXT records used to publish current TZ information. OS Vendors can cache all that in the OS if they like, but this secondary central time authority has outlived it's usefulness.
Let's say we schedule a meeting for next year at 15:00 local time in SF. You store that as an UTC timestamp of 2025-08-24 22:00 and America/Los_Angeles timezone. Now, imagine California decides to abolish daylight savings time and stay on UTC-8 next year. Our meeting time, agreed upon in local time, is now actually for 23:00 UTC.
Google Photos also get confused with "When was this picture taken?", my older model camera just stores the EXIF date in "local time" and I have to remember to change its timezone when travelling, and if GPhotos can't figure it out, it might show pictures out of the airplane window, and then the next series of pictures are from the departure airport because they're from a "later" hour (since it's missing the timezone info).
I suppose I could keep it at my home time or UTC...
The photos problem is harder, but the app needs to just convert it from local time to UTC when you import it. There's not much that can be done if you take photos on a camera with a different time zone than you're in without more metadata.
> That is how I would expect a bank statement to read though. I would find it infinitely more confusing if I bought something online in my bank showed the time of wherever the seller was located.
When using my banking app abroad (one that does show timestamps), I'm usually much more confused by their presence than by their absence.
> The photos problem is harder, but the app needs to just convert it from local time to UTC when you import it.
But I usually want to see the time in local hours and minutes for photos! Sunsets, new year's fireworks etc. happen according to local time, not UTC or my current timezone's offset.
Sometimes, the local time at the place the photo was taken can make more sense, but it's not a general rule.
I've seen some software work around that by combining the local date/time with an embedded GPS tag, if present, which does contain the time in UTC.
[0] https://en.wikipedia.org/wiki/Daylight_saving_time_by_countr...
These days I try to encode everything that is logically a date as yyyy-mm-dd. And if I need to do math with it, I often work with an offset julian date as an integer. But that only works if you stay on this side of September 1752:
Wouldn't using Julian days prevent the ordinary problems involved with doing calendar math across a renumbering of the dates?
That way, you can identify all of:
- Future timestamps you might want to re-process, e.g. for notification scheduling, because the future UTC conversion has changed between scheduling/updating the event and now.
- Equivalently, timestamps written by software/an OS running an outdated TZ database. You should talk to them; things are about to go wrong if the date is in the non-too-far future!
- Trivially and without conversion, the local time that people will use in the meeting notes, documenting that you missed the meeting because you didn't update your TZ database and dialed in to the meeting an hour late
Or what if it is specifically about time in timezone independent way? You want to wake up ate 06:00 no matter in any timezone. Just something like alert.
You could use part of ISO8601 like 2020-02-02 or 06:00:00 to store exactly what you specify. But with timestamp, not so much.
Often it feels like you can "just use UTC" because it's hard to imagine the fail states, and APIs often make tz assumptions for you so you may never notice those fail states (occasionally your software will just be buggy and annoy a user, decreasing the feeling of quality and trust - it may never result in a disaster).
Edit to add: still, this sounds like a great improvement. A common mistake that naive programmers make is to believe that they can hand-roll their own date/time functions. And JavaScript sort of forces them to do that.
See also Falsehoods programmers believe about time at https://gist.github.com/timvisee/fcda9bbdff88d45cc9061606b4b...
For example, if you are trying to say “run this task at this specific time in Los Angeles time” and you put a specific UTC offset, it just doesn’t make any sense. Los Angeles time consists of two offsets, and yet here you openly put down something wrong. You need to put into your system literally Los Angeles time (like America/Los_Angeles) because that’s what you want. You didn’t want an offset. Dear god why are you putting an offset then?
Or you want to define a specific date but then you put into your system a date with a time like 12/12/2024 00:00. Like you started off with “I want to define a specific date” and here you openly just put a time. You had to make up 00:00. Why are you just doing random things without thinking?
There are date/time libraries that can't get all of this right, but you'll come a lot closer using them than you will rolling your own.
Don't store raw timestamps. Don't store offsets. Use date/time data types.
I can tell you from bitter experience that if you have an event where a person has to arrive at a place at a time and you store that as UTC instead of wall clock, you will have a problem at some point
Maybe a better argument is, “when you’re setting a phone alarm, you don’t tell it a timezone.” Maybe the distinction is whether the timezone is established at write time or read time.
Which coincidentally and ironically makes phone alarms surprisingly difficult to implement in a way that does not break in the face of DST shifts, timezone changes etc., as Apple has learned the hard way a couple of times.
Past/future does matter, as generally speaking it's possible to accurately convert between local time and UTC for times in the past, but not in the future.
There's a few exceptions where governments have retroactively changed timezones or DST rules, but at that point you've lost anyway.
The future is defined by intent which is imprecise (will Oregon drop daylight savings time or not — who knows?). I don’t know how many seconds it is until my next birthday, but I know exactly how many have passed since I was born.
That poor Jedi master is going to miss the recurring workgroup meeting at least twice per year though, after either DST switch :)
Maybe I'm thinking of a group with less experience than you had in mind, but novices do not even know about UTC.
Presumably this new API will fix the fact that JS does in fact know about some time zones, but not most.
Shield your eyes from this monstrosity that will successfully parse some dates using `new Date(<string>)` in some select special time zones, but assume UTC in the other cases:
https://github.com/v8/v8/blob/781c20568240a1e59edcf0cb5d713a...
This bit me hard in a previous role. :'(
It knows about 8 time zones in 4 different offsets, and that's it?
I ask because yes, everything on the site points that way. But it's still so hard to believe that some confirmation would be good.
Unofficially schools tell students to use Chrome because some tasks fail often outside of Chrome. In particular Safari's default settings for cookies/privacy often causes the system to fail - particularly with integrations that use iframes/popups and other antiquated tricks.
The year is 2024.
I feel like we peaked somewhere around the mid 2010s with regards to application compatibility: No more Flash, but also more than just 1.5 rendering engines.
Before that, it was all "oh, sorry, Windows .exe only"; since then, "sorry, Chrome visitors only".
I don't think this is correct. I think the JavaScript spec here defines a string format which is extremely narrow, but then leaves it open to browsers implementing whatever they want.
https://262.ecma-international.org/5.1/#sec-15.9.4.2
> The function first attempts to parse the format of the String according to the rules called out in Date Time String Format (15.9.1.15). If the String does not conform to that format the function may fall back to any implementation-specific heuristics or implementation-specific date formats.
https://262.ecma-international.org/5.1/#sec-15.9.1.15
> ECMAScript defines a string interchange format for date-times based upon a simplification of the ISO 8601 Extended Format. The format is as follows: YYYY-MM-DDTHH:mm:ss.sssZ
> Z is the time zone offset specified as “Z” (for UTC) or either “+” or “-” followed by a time expression HH:mm
> Note2: There exists no international standard that specifies abbreviations for civil time zones like CET, EST, etc. and sometimes the same abbreviation is even used for two very different time zones. For this reason, ISO 8601 and this format specifies numeric representations of date and time.
The hint as to what is going on then comes from MDN, which more documents the ground truth than the goal.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
> There are many ways to format a date as a string. The JavaScript specification only specifies one format to be universally supported: the date time string format, a simplification of the ISO 8601 calendar date extended format. The format is as follows: YYYY-MM-DDTHH:mm:ss.sssZ
> Note: You are encouraged to make sure your input conforms to the date time string format above for maximum compatibility, because support for other formats is not guaranteed. However, there are some formats that are supported in all major implementations — like RFC 2822 format — in which case their usage can be acceptable. Always conduct cross-browser tests to ensure your code works in all target browsers. A library can help if many different formats are to be accommodated.
That table then comes from RFC2822, which also doesn't want you to use string named time zones, but as RFC822 has such it needs to still support it a bit--I imagine this probably came from back when this was used by ARPA-- and so has a section on "obsolete" date and time format extensions, which only explicitly requires support for US time zones and (notably) military formats.
https://datatracker.ietf.org/doc/html/rfc2822#section-4.3
> Other multi-character (usually between 3 an...Anyway, yeah, that does explain the situation we are in. And yeah, it looks like if you are extremely literal-minded and insist on supporting obsolete notations on your new thing, that would make your code be exactly like the one the OP pointed.
It's a bad decision all around, because the RFC 2822 isn't concerned about general purpose time handling. A programing language shouldn't use something like this.
Somebody posted the spec as a reply, and looks like the standard can be read in a way that mandates exactly that.
Having worked with dates and times in both Java and JavaScript, I'm very happy with what I see in the temporal API. Huge improvement.
But yes I agree. There's no way any other standard could resist a standard adopted by the IETF and implemented by the language of the web
> Timestamps with Additional Information
Oh, cool, we're finally adopting TAI!
The answer to this is RFC 9557, which was recently published. Rust's Jiff library (of which I am the author) supports it. And I believe java.time supports it. Otherwise, yes, adoption will take time. But it's the right way forward I think.
The author confuses the concept of injectivity and well-definedness. For an injective function f, it has to be true that given distinct a and b, f(a) != f(b). That's not the problem here; rather the problem is that for a timestamp t there's no unique human-readable date x such that f(t) = x. That's well-definedness, not injectivity.
https://en.wikipedia.org/wiki/Well-defined_expression
You could talk about the inverse function, from human-readable dates to timestamps, and correctly point out that that function is not injective, because more than one human-readable date maps to the same timestamp...
if t is 17943000... whatever
which translates to say
03:50 AM on Mar 16, 2020 in Greenwich (i.e. UTC+00.00)
then it can be converted to any other human readable zoned time.
Where is the issue?
For example, given just a timestamp, you don't even know what day it was. Was the user in New York? That 3:50am was actually 11:50pm on March 15th.
I would assume in 99% of cases the user is simply just interested in his local time anyway.
If you really need the location info, then you would obv have to make some other tradeoffs like either
1) always store the location alongside the timestamp or
2) complicate (probably massively so) the time format, storing and parsing/processing logic
But I don't see how that's an issue of UTC timestamps per se rather than being an issue of requiring more information than just time (i.e. time AND location at the time).
Again, really would appreciate an explanation of where I am mistaken here because thus far the whole point of OP seems like a trivial non-issue to me.
“5 days ago.”
“3 hours and 33 minutes.”
I’ve found this kind of thing to be the main reason I have to drag MomentJS along for the ride.
Likewise. It feels long overdue to have template based formatting natively.
I’m confident ChatGPT or Claude will write you one with one-shot prompt that does exactly what you want. Here’s an attempt at that: https://chatgpt.com/share/9bfe1d60-34cc-46fc-8327-3474c4a7d6...
Anything for maybe the last hour or I can see; "1 day and 5 hours ago" and making me hover over the string (and pray that there's an alt text available that I still can't copy-paste) is very annoying.
I really wish, space permitting, web designers would start at least including the actual timestamp in the regular/non-alt text as well, at the very least for professional tools if not for social media sites.
One time it works is when your team is across many time zones, the data being listed spans many time zones, and what’s important is knowing the recent events from older ones. And yes, also showing the absolute UTC stamps too
https://pkg.go.dev/time#Date
Their datetime formatting implementation is simply nuts. Why not follow standards? Why the NIH?
Well, about time.
Currently the "Number" type is used for every number and it gets stored as a double, and can "only" represent "integers" safely in the range of ±(2^53 -1). Though there is a "BigInt" [1] type.
[0] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data...
[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data...
* Integer types of various sizes (for efficiency) and so you don't have to constantly do floating point comparisons (i.e. equal within a small delta) and generally have better compatibility with other languages. * Decimal floating point type so you can work in base-10 and don't have rounding issues.
Plus all of the error checking you get for free if you're using typescript instead of raw-dogging it with plain javascript or coffee-script :-)
I can't wait for it to be fully taken advantage of by things such as mui's date time picker. Imagine if after selecting the fall back day, it saw the transition and let you pick a time during the extra hour. If after selecting the spring forward day, it wouldn't let you pick a time during the hour that doesn't exist. Today that doesn't work because everyone uses different crappy third-party libraries and mui functions on top of a lowest-common adapter that certainly doesn't do stuff like "show me the DST transitions in this day".
This stuff matters sometimes; a user of my NVR wanted to save a clip during the fall back hour and got the wrong result because these things just don't work right today. https://github.com/scottlamb/moonfire-nvr/issues/244
"Let's consider an example: suppose I want to record the moment I make a payment with my card. Many people might be tempted to do something like this:
const paymentDate = new Date('2024-07-20T10:30:00');".
What? I don't think anybody would define a date like this to record some moment. Most developers would simply use new Date() without any parameters, thereby creating a timezone-safe absolute underlying timestamp value. This value then is of course stringified relative to the timezone of the caller when retrieving it, but that's expected.
The new Temporal api might be nice but it doesn't need flawed examples to make its case.
Note that there's also a Rust datetime crate, jiff, that's inspired by the Temporal API and features zone-aware datetimes (from burntsushi, author of ripgrep and Rust's regex library): https://crates.io/crates/jiff
And won't be available in non-chromium browsers and LTS versions of Node until 2028.
So the new API will be a very welcome addition to the JS standard library.
However, and this is probably a bit off-topic, why are the ECMAScript guys not also addressing the fundamental reasons why JS continues to be somewhat a joke of a language?
- Where are decimals, to avoid things like `parseInt(0.00000051) === 5`?
- Why are inbuilt globals allowed to be modified? The other day a 3rd-party lib I was using modified the global String class, and hence when I attempted to extend it with some new methods, it clashed with that modification, and it took me and hour or two to figure out (in TS, no less).
- Why can't we have basic types? Error/null handling are still haphazard things. Shouldn't Result and Maybe types be a good start towards addressing those?
Because that was the original behavior, and you can't just change that behaviour, or half of the web will break (including that 3rd party lib and every web site depending on it)
> Why can't we have basic types? ... Shouldn't Result and Maybe types
Neither Result nor Error are basic types. They are complex types with specific semantics that the entire language needs to be aware of.
Being wedded to mistakes made in the past for fear of breaking current usage is the root of all programming language evil.
How do you imagine doing that?
> Being wedded to mistakes made in the past for fear of breaking current usage is the root of all programming language evil.
Ah yes, let's break large swaths of the web because progress or something
Like, you are asking for a Result type. If this was added to the spec tomorrow and existing objects were updated with new methods that return Result, and you can't modify built-in types, then you can't actually use the shiny new feature for years.
On the specific point of Maybe type, I think it's not very useful for a dynamically typed language like JS to have "maybe". If there's no compiler to check method calls, it's just as broken to accidentally call `someVar.doThingy()` when `someVar` is null (classic null pointer error) versus call `someVar.doThingy()` when someVar is Some<Stuff> or None, in either case it's "method doThingy does not exist on type Some<...>" or "method doThingy does not exist on type None".
And that's a good thing, because you know that with a specific version of JS, the inbuilts are fixed; no mucking around to know what exactly you have, and no global conflicts. I find it surprising that you would defend this insane state of affairs. If you have worked on really large JS projects, you would see my point immediately.
It is like saying the immutability of functional programming is a bad thing because it limits you. The immutability is the point. it protects you from entire classes or errors and confusion.
> If all the built-in types were locked down, we'd end up using those built-in types less because we'd more frequently need to use userspace libraries for the same things.
This is the correct solution for now.
There is a draft proposal for this: https://github.com/tc39/proposal-decimal
Additionally, BigInt has been available for years: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe... (unfortunately does not serve as a u64 / i64 replacement due to performance implications and lack of wrapping/overflow behavior)
> - Why are inbuilt globals allowed to be modified?
> Error/null handling are still haphazard things.
How would you suggest addressing these in a way that is backwards compatible with all existing web content?
Version numbers. Solving the problem in the future but not the past is still better than leaving it unsolved in the future and the past.
The same reason you couldn't in 1996: because the assumed entry point for the language is someone who can barely conceptually manage HTML; doesn't want to have to deal mentally with the fact that numbers and text are fundamentally different kinds of thing; and - most importantly - absolutely will not accept the page failing to render correctly, or the user being shown an error message from the browser, for any reason that the browser could even vaguely plausibly patch around (just like how the browser has to guess whether an unescaped random stray < is just an unescaped less-than symbol or the start of an unclosed tag, or guess where the ends of unclosed tags should be, or do something sensible about constructs like <foo><bar></foo></bar>, or....)
I personally dislike decimals, I would prefer a full BigRational that is stored as a ratio of two BigInts (or as a continued fraction with BigInts coefficients.
Decimals solve the 0.1+0.1+0.1!=0.3 error but are still broken under division.
So JavaScript gets what Java got in version 8, 10 years ago?