This article lists several of the absurdities of the Date constructor, but only barely touches on the most unforgivable one. The example from the article is:
// Unless, of course, you separate the year, month, and date with hyphens.
// Then it gets the _day_ wrong.
console.log( new Date('2026-01-02') );
// Result: Date Thu Jan 01 2026 19:00:00 GMT-0500 (Eastern Standard Time)
In this example, the day is "wrong" because the constructor input is being interpreted as midnight UTC on January 2nd, and at that instantaneous point in time, it is 7pm on January 1st in Eastern Standard Time (which is the author's local time zone).
What's actually happening here is a comedy of errors. JavaScript is interpreting that particular string format ("YYYY-MM-DD") as an ISO 8601 date-only form. ISO 8601 specifies that if no time zone designator is provided, the time is assumed to be in local time. The ES5 spec authors intended to match ISO 8601 behavior, but somehow accidentally changed this to 'The value of an absent time zone offset is “Z”' (UTC).
Years later, they had realized their mistakes, and attempted to correct it in ES2015. And you can probably predict what happened. When browsers shipped the correct behavior, they got too many reports about websites which were relying on the previous incorrect behavior. So it got completely rolled back, sacrificed to the altar of "web compatibility."
For more info, see the "Broken Parser" section towards the bottom of this article:
>So it got completely rolled back, sacrificed to the altar of "web compatibility."
This is why I don't understand the lack of directives.
'use strict'; at the top of a file was ubiquitous for a long time and it worked. It didn't force rolling back incompatibilities, it let you opt into a stricter parsing of JavaScript.
It would have been nice for other wide changes like this to have like a 'strict datetime'; directive which would opt you into using this corrected behavior.
They couldn't and shouldn't do this sort of thing for all changes, but for really major changes to the platform this would be an improvement.
Or they could go all in on internal modules, like how you can import `node:fs` now. They could include corrected versions of globals like
I very much remember coding a function that split the string on their components and then rebuild them to ensure the date was created without time zone.
Sometimes a date is just a date. Your birthday is on a date, it doesn't shift by x hours because you moved to another state.
The old Outlook marked birthdays as all-day events, but stored the value with time-zone, meaning all birthdays of people whose birthday I stored in Belgium were now shifted as I moved to California...
I always found it weird when systems code dates as DateTime strings. There needs to be a different primitive for Date, which is inherently timezone-less, and DateTime, which does require a timezone.
After having a bunch of problems with dealing with Dates coded as DateTime, I've begun coding dates as a Date primitive, and wrote functions for calculation between dates ensuring that timezone never creeps its way into it. If there is ever a DateTime string in a Date column in the database, it's impossible to know what the date was supposed to be unless you know you normalized it at some point on the way up.
Then I found that a lot of DatePicker libraries, despite being in "DATE" picker mode, will still append a local timezone to its value. So I had to write a sanitizer for stripping out the TZ before sending up to the server.
That said, I am pretty excited about Temporal, it'll still make other things easier.
I mean... That's kinda how it works? More than once I've halfway forgotten birthdays of friends who live in timezones to my east, and then sent them a message saying "Happy birthday! (It still is where I am, lol)".
I'm not necessarily defending the implementation, just pointing out another way in which time is irreducibly ambiguous and cursed.
A reminder associated with the birthday can and should be changed if I change time zones. But the birthday date didn’t change so it shouldn’t move to a different day.
> But the birthday date didn’t change so it shouldn’t move to a different day.
But it does. My brother moved to the US for a few years. So we’d send him birthday wishes on the day of his birthday (Australia time), and he’d get them the day before his birthday (his time). Now he’s moved back to Australia, the same thing happens in reverse-he gets birthday wishes from his American friends the day after his birthday.
My wife has lots of American friends on Facebook (none of whom she knows personally, all people she used to play Farmville with)-and she has them wishing her a happy birthday the day after her birthday too. Maybe she’s doing the same to them in reverse.
I agree with the "don't break the web" design principle, but I sometimes disagree with precisely where TC39 draws the line. There is obviously a cost to breaking old, unchanging websites. But there's also a cost to allowing old, unchanging websites to hold the entire web hostage. Balancing those costs is a subjective matter.
As far as I know, TC39 doesn't have any clear guidelines about how many websites or how many users must be affected in order to reject a proposed change to JavaScript behavior. Clearly there are breaking changes that are so insignificant that TC39 should ignore them (imagine a website with some JavaScript that simply iterates over every built-in API and crashes if any of them ever change).
Have an optional parameter to opt in to the old behaviour and keep the new correct behaviour the default (without the parameter) seems like a decent choice.
To preserve backwards compatibility and not require all those old sites to update, the legacy behavior would have to be the default, with opt-in for the new behavior.
I think NaN itself is a bit of an error object, especially in how it's passed through subsequent math functions, which is a different choice than throwing up.
But besides that I think you're right, Invalid Date is pretty weird and I somehow never ran into it.
One consequence is you can still call Date methods on the invalid date object and then you get NaN from the numeric results.
the new Date() constructor is an amalgamation of like 5 different specs, and unless the input matches one of them, which one kicks in is up to the implementer's choice
It's a common source of off-by-one date formatting bugs in client-rendered web apps, particularly ones that pass around "YYYY-MM-DD" date strings (common for OpenAPI JSON APIs).
const dateStringFromApiResponse = "2026-01-12";
const date = new Date(dateStringFromApiResponse);
const formatter = new Intl.DateTimeFormat('en-US', { dateStyle: 'long' });
formatter.format(new Date("2026-01-12"));
// 'January 11, 2026'
Personally, I like that UTC is the default time zone. Processing of dates should happen in a standardized time zone. It’s only when you want to display it that the date should become local.
This will result in incorrect behavior when, between converting to UTC and back to the original timezone, the timezone database has changed, which happens more often than you think.
There's a lot wrong with Javascript's Date, but the fact that it's an object is is not really in the top 10.
Would it have been nice if the Date object had been immutable? Sure, but the fact that changing the mutable object does indeed change the object shouldn't be a shock
It's definitely a shock when something else changes the date object you've been holding on to. The problem with mutable values has never been when you (that is, the local context) change them. It's always that you can't trust that nothing else (some very non-local code) does.
I do find it annoying how the Temporal API, just like nearly all other datetime APIs, has 0 support for querying leap-second information in any shape or form. Suggested workarounds like temporal-tai all require plugging in a leap-second file and keeping it updated, which is especially painful for client-side JS, where you can't just download a leap-second file from someone else's site thanks to the SOP. Meanwhile, browsers update on a cadence more than sufficient to keep an up-to-date copy, but the datetime APIs refuse to expose leap-second info because they're too committed to "only UTC is in-scope for this project".
(The context is that I want to write some JS tools for astronomical calculations, but UTC conversions need leap-second info, so this trend makes it impossible to write something that Just Works™.)
> where you can't just download a leap-second file from someone else's site thanks to the SOP
WDYM by this? Why does the SOP prevent a website from hosting a leap seconds file? All they need to do is set Access-Control-Allow-Origin to allow websites to access it. Or provide it as a JS file—in which case no headers are necessary at all. All the SOP prevents is you hotlinking someone else's leap-seconds file and using their bandwidth without their opt-in.
> Meanwhile, browsers update on a cadence more than sufficient to keep an up-to-date copy
Is this true? I don't know any browser right now that ships with a copy of a leapseconds data file. Adding such a data file and keeping it up to date would probably be a pretty non-trivial task for new browser developers—just for something the browser will never end up using itself. It's not like the ICU/CLDR files where browsers are going to need them anyway for rendering their own user-interface components.
> All they need to do is set Access-Control-Allow-Origin to allow websites to access it. All the SOP prevents is you hotlinking someone else's leap-seconds file and using their bandwidth without their opt-in.
They can, but the major providers (read: the ones I would trust to update it) don't. The IERS doesn't [0], the USNO doesn't [1], IANA doesn't [2], and NIST uses FTP [3]. Keep in mind that these files are constantly being downloaded by various clients for NTP and whatnot, it's not like these providers want to restrict public access, they just don't bother to set the header that would allow JS requests.
> Is this true? I don't know any browser right now that ships with a copy of a leapseconds data file.
From ECMA-262:
> It is required for time zone aware implementations (and recommended for all others) to use the time zone information of the IANA Time Zone Database https://www.iana.org/time-zones/.
Any browser that ships with a copy of tzdb, or knows where to find a copy from the OS, should have access to its leapseconds file. Unless you mean that all of them go solely through ICU and its data files? Which I suppose could be an obstacle unless ICU were to start exposing them.
> but the datetime APIs refuse to expose leap-second info because they're too committed to "only UTC is in-scope for this project".
This doesn't make sense on at least two different levels.
First, pedantically, the definition of UTC as a time scale is that it includes leap seconds. So if you're committed to UTC, then you're supporting leap seconds.
Second, and to more broadly address your point, you should say, "they're too committed to 'only the POSIX time scale is in-scope for this project.'" That more accurately captures the status quo and also intimates the problem: aside from specialty applications, basically everything is built on POSIX time, which specifically ignores the existence of leap seconds.
Sure, but my gripe isn't even that we ought to change the "POSIX time by default" status quo (the ship has long sailed that everyone counts durations by 'calendar seconds'), it's that the underlying libraries don't even provide enough information for "specialty applications" to reliably correct for it, short of perpetually updating it themselves.
Why should they though? To me it seems like a niche of a niche. I think there is plenty of room for scientific datetime libraries to service this need in a way that is likely better than what a general purpose datetime library would provide. (And indeed, there are many of them.)
I say this as someone who had leap second support working in a pre-release version of Jiff[1] (including reading from leapsecond tzdb data) but ripped it out for reasons.[2]
That's part of it: If I were writing a standalone program that could extract info from tzdb or whatever, I'd happily jump through those hoops, and not bother anyone else's libraries. I don't really care about the ergonomics. But for JS scripts in particular, there is no information available that is not provided by either the browser APIs or someone's server. And such servers are not in great supply.
The article is super weird. It never mentions Date.now(). It dances around the subject and exhaustively mentions the equivalent convention for Temporal.
If you want Date to act like Temporal then only use Date.now() as your starting point. It generates the number of milliseconds since 1 Jan 1970. That means the starting output is a number type in integer form. It does not represent a static value, but rather the distance between now and some universal point in the past, a relationship. Yes, Temporal is a more friendly API, but the primary design goal is to represent time as a relational factor.
Then you can format the Date.now() number it into whatever other format you want.
the article has examples of unexpected behavior with timestamps too, so... How do you covert to your desired format without going through Date? Please don't say date-fns
// A numeric string between 32 and 49 is assumed to be in the 2000s:
console.log( new Date( "49" ) );
// Result: Date Fri Jan 01 2049 00:00:00 GMT-0500 (Eastern Standard Time)
// A numeric string between 33 and 99 is assumed to be in the 1900s:
console.log( new Date( "99" ) );
// Result: Date Fri Jan 01 1999 00:00:00 GMT-0500 (Eastern Standard Time)
It is a lot more complex than moment, but only because there's a lot of inherent complexity to dates and times that moment just doesn't deal with. So you need to be explicit about whether you're dealing with dates, times, or datetime objects, whether or not the object you're working with has a timezone, etc. Where moment is generally designed to have a convenient API, Temporal is designed to have a correct API.
Built a scheduler with pretty much all my moment/moment-tz questions answered through ChatGPT. One of the things it excels at, crawling long lived API documentation, answers, etc.
The Date API is fine and relatively normalized. Once you understand it it's very easy to work with. It's biggest problem is that it simply does not support timezones, which is the main reason to use Temporal.
Checking its API, I'm surprised that Temporal.Duration has a constructor with many parameters for years, months, days, ... all the way to nanoseconds, while Temporal.Instant has no way at all to create it given a current year/month/day, only from unix timestamp equivalents (or strings)
That seems to be functionality you'd want to have? Or is the intention you convert your numbers to string first and then back to a Temporal.Instant?
It's perfectly reasonable to default seconds, minutes, hours, etc. to zero in the Duration constructor. But for Instant, it doesn't make sense to default those to zero unless you specify time zone offset.
And indeed, the static method Instant.from does accept an RFC 9557 string, which requires a 2-digit hour and a time zone offset, but can omit minutes and seconds:
I guess they don’t want people getting confused between local and UTC values for the fields in the constructor (especially as if it took local values it would need to handle DST transitions)
it's because a year/month/date isn't enough to uniquely identify an instant in time. you can create a Temporal.PlainDate(Time) with those values though, then convert to the other types depending on what you need and it needs (e.g. time zone)
So, hold on--the author's soul-breaking complaint isn't all of the "quirks" and inconsistencies with the Date functions, but rather the fact that it's an object? Specifically, an object with mutable properties in a language when all objects have mutable properties?
I mean, the author's conclusion is correct. But I disagree with the rationale. It's like hating an evil dictatorship because they use the wrong font in their propaganda.
> When an immutable value is assigned to a variable, the JavaScript engine creates a copy of that value and stores the copy in memory
Not exactly. The language doesn't specify whether the value is copied or not and, precisely because values are immutable, there's no way for a user to tell if it was or wasn't.
For example, strings are also immutable value types, but you can be certain that no JS engine is fully copying the entire string every time you assign one to a variable or pass it to a parameter.
The current global availability of native Temporal is 1.81%. For context, IE11(!) has a higher global usage than Temporal has native support. For my organization, this likely means we're years from being able to use Temporal in production, because getting the polyfills approved is such a hassle.
Keep in mind that even as of December last year, Chrome didn't ship with it yet (i.e. support is less than one month old). Safari still does not.
Good article, but “Java deprecated their Date way back in 1997” is not exactly true. They deprecated a lot of methods and constructors in JDK1.1 when Calendar was introduced, but the class itself was never deprecated and it was the preferred way to represent a point in time until the “modern” approach was provided in java.time in JDK8 (c2014)
(I can't find the 1.1 docs, but they were the same)
It's one of my favourite examples of how languages pretty much always get date and time hopelessly wrong initially. Java now has one of the best temporal APIs.
Yeah, it effectively became a typed wrapper of a long epoch millis value. Generally treated as immutable by convention in my experience, although of course it technically wasn't as the setters were never removed.
It was hopelessly wrong initially, and got even worse when they added the horrible sql Date/Timestamp/etc classes.
With java.time though, it is the gold standard as far as I've seen.
related: i had to jump through the Date hoops recently (again) when rewriting uPlot's DST and timezone handling, but i'm pretty happy with the result that avoided much complexity, performance loss, and adding a dependency: https://github.com/leeoniya/uPlot/pull/1072
Late by a decade or more (JSR310 was released in 2014), but still a good development. I've tried convincing colleagues to use js-joda in the past but they thought they were keeping it simple by sticking to moment.js. They weren't.
Temporal objects do not store formatting information. Unless you mean e.g. dropping the time, using a different time zone, etc - but those aren't formatting changes, they logically change the semantics of the data. Just like `myInt += 1` is not changing the "formatting" of `myInt`.
Remember: Date and Temporal objects are logically different things. A Date represents an absolute point in time (a timestamp), while a Temporal object represents a human time (calendar date, clock time, time zone). The fact that Dates are used to represent human time for lack of a better structure is the entire problem statement - the hole that all these other APIs like Temporal try to fill in.
I just groked it before and thought "plain" in `Temporal.PlainDateTime` indicates some specific format instead of just being zoneless. It is actually always using ISO8601 fur build in toString conversions, so I don't really have anything to complain about.
Is Temporal even in though? Last I checked (last year or so), I had to use some bleeding edge version of Firefox to get it, and absolutely nothing else had it. I do agree though it's lovely, and I'd love to see native support for it.
Nope. Only Firefox and Chrome have it, in their latest versions. No Safari or Edge support yet. So this article is a bit premature (unless you use the polyfill.)
> My complaint is about more than parsing or syntax or “developer ergonomics” ... My problem with Date is that using it means deviating from the fundamental nature of time itself.
I don't really have a problem with the substance of this blog post. I have a problem with this exaggerated writing style. It means deviating from the fundamental purpose of writing itself!
I had to scroll all the way to the end to find the actual point, and it was underwhelming.
> Unlike Date, the methods we use to interact with a Temporal object result in new Temporal objects, rather than requiring us to use them in the context of a new instance
Bro, just be honest. This entire blog post was totally about developer ergonomics and that's okay. We all hate the way Date works in javascript.
It's not an exaggeration - you're used to dramatic phrases that use similar wording ("fundamental nature of time itself"), but in this case it's a regular old literally-true statement. Date is used to represent two things: Timestamps and human times (date, time, tz). But it only actually represents the former. Using it to represent the latter is a hack we simply put up with.
This article lists several of the absurdities of the Date constructor, but only barely touches on the most unforgivable one. The example from the article is:
In this example, the day is "wrong" because the constructor input is being interpreted as midnight UTC on January 2nd, and at that instantaneous point in time, it is 7pm on January 1st in Eastern Standard Time (which is the author's local time zone).What's actually happening here is a comedy of errors. JavaScript is interpreting that particular string format ("YYYY-MM-DD") as an ISO 8601 date-only form. ISO 8601 specifies that if no time zone designator is provided, the time is assumed to be in local time. The ES5 spec authors intended to match ISO 8601 behavior, but somehow accidentally changed this to 'The value of an absent time zone offset is “Z”' (UTC).
Years later, they had realized their mistakes, and attempted to correct it in ES2015. And you can probably predict what happened. When browsers shipped the correct behavior, they got too many reports about websites which were relying on the previous incorrect behavior. So it got completely rolled back, sacrificed to the altar of "web compatibility."
For more info, see the "Broken Parser" section towards the bottom of this article:
https://maggiepint.com/2017/04/11/fixing-javascript-date-web...
>So it got completely rolled back, sacrificed to the altar of "web compatibility."
This is why I don't understand the lack of directives.
'use strict'; at the top of a file was ubiquitous for a long time and it worked. It didn't force rolling back incompatibilities, it let you opt into a stricter parsing of JavaScript.
It would have been nice for other wide changes like this to have like a 'strict datetime'; directive which would opt you into using this corrected behavior.
They couldn't and shouldn't do this sort of thing for all changes, but for really major changes to the platform this would be an improvement.
Or they could go all in on internal modules, like how you can import `node:fs` now. They could include corrected versions of globals like
`import Date from 'browser:date';`
has corrected behavior, for example
I very much remember coding a function that split the string on their components and then rebuild them to ensure the date was created without time zone.
Sometimes a date is just a date. Your birthday is on a date, it doesn't shift by x hours because you moved to another state.
The old Outlook marked birthdays as all-day events, but stored the value with time-zone, meaning all birthdays of people whose birthday I stored in Belgium were now shifted as I moved to California...
I always found it weird when systems code dates as DateTime strings. There needs to be a different primitive for Date, which is inherently timezone-less, and DateTime, which does require a timezone.
After having a bunch of problems with dealing with Dates coded as DateTime, I've begun coding dates as a Date primitive, and wrote functions for calculation between dates ensuring that timezone never creeps its way into it. If there is ever a DateTime string in a Date column in the database, it's impossible to know what the date was supposed to be unless you know you normalized it at some point on the way up.
Then I found that a lot of DatePicker libraries, despite being in "DATE" picker mode, will still append a local timezone to its value. So I had to write a sanitizer for stripping out the TZ before sending up to the server.
That said, I am pretty excited about Temporal, it'll still make other things easier.
Temporal does have PlainDate, which is the Date primitive you're describing (by a different name, presumably to not collide with the old Date type).
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
I mean... That's kinda how it works? More than once I've halfway forgotten birthdays of friends who live in timezones to my east, and then sent them a message saying "Happy birthday! (It still is where I am, lol)".
I'm not necessarily defending the implementation, just pointing out another way in which time is irreducibly ambiguous and cursed.
A reminder associated with the birthday can and should be changed if I change time zones. But the birthday date didn’t change so it shouldn’t move to a different day.
> But the birthday date didn’t change so it shouldn’t move to a different day.
But it does. My brother moved to the US for a few years. So we’d send him birthday wishes on the day of his birthday (Australia time), and he’d get them the day before his birthday (his time). Now he’s moved back to Australia, the same thing happens in reverse-he gets birthday wishes from his American friends the day after his birthday.
My wife has lots of American friends on Facebook (none of whom she knows personally, all people she used to play Farmville with)-and she has them wishing her a happy birthday the day after her birthday too. Maybe she’s doing the same to them in reverse.
> sacrificed to the altar of "web compatibility."
What should they have done instead? Force everybody to detect browser versions and branch based on that, like in the olden days of IE5?
(Serious question, maybe I'm overlooking some smart trick.)
Browsers should version their languages. They should say "if you use <html version="5.2"> or bigger, this is the behavior".
Somehow, the standard groups decided to remove the versioning that was there.
I agree with the "don't break the web" design principle, but I sometimes disagree with precisely where TC39 draws the line. There is obviously a cost to breaking old, unchanging websites. But there's also a cost to allowing old, unchanging websites to hold the entire web hostage. Balancing those costs is a subjective matter.
As far as I know, TC39 doesn't have any clear guidelines about how many websites or how many users must be affected in order to reject a proposed change to JavaScript behavior. Clearly there are breaking changes that are so insignificant that TC39 should ignore them (imagine a website with some JavaScript that simply iterates over every built-in API and crashes if any of them ever change).
Have an optional parameter to opt in to the old behaviour and keep the new correct behaviour the default (without the parameter) seems like a decent choice.
To preserve backwards compatibility and not require all those old sites to update, the legacy behavior would have to be the default, with opt-in for the new behavior.
You might want to play with https://jsdate.wtf/
One can't fathom how weird JS Date can be.
Guessed 2 of the first 3 questions.
Got to question 4 and gave up:
There's literally no way of guessing this crap. It's all random.I had no idea we even had an `Invalid Date` object, that's legitimately insane. Some other fun ones:
are both valid dates lol.The choice here is really surprising. I was half-expecting NaN, that you omitted.
Is there any other instance of the standard JS library returning an error object instead of throwing one? I can't think of any.
I think NaN itself is a bit of an error object, especially in how it's passed through subsequent math functions, which is a different choice than throwing up.
But besides that I think you're right, Invalid Date is pretty weird and I somehow never ran into it.
One consequence is you can still call Date methods on the invalid date object and then you get NaN from the numeric results.
the new Date() constructor is an amalgamation of like 5 different specs, and unless the input matches one of them, which one kicks in is up to the implementer's choice
If this is comedy, sign me up for tragedy.
This feels like something that must be the root of innumerable small and easily overlooked bugs out there.
It's a common source of off-by-one date formatting bugs in client-rendered web apps, particularly ones that pass around "YYYY-MM-DD" date strings (common for OpenAPI JSON APIs).
I'm having flashbacks to writing Power Automate expressions to reconcile Dates passed from Outlook metadata to Excel
Basically just extracting numbers from string index or regex and rearranging them to a string Excel would recognize
Personally, I like that UTC is the default time zone. Processing of dates should happen in a standardized time zone. It’s only when you want to display it that the date should become local.
This will result in incorrect behavior when, between converting to UTC and back to the original timezone, the timezone database has changed, which happens more often than you think.
There's a lot wrong with Javascript's Date, but the fact that it's an object is is not really in the top 10.
Would it have been nice if the Date object had been immutable? Sure, but the fact that changing the mutable object does indeed change the object shouldn't be a shock
It's definitely a shock when something else changes the date object you've been holding on to. The problem with mutable values has never been when you (that is, the local context) change them. It's always that you can't trust that nothing else (some very non-local code) does.
I do find it annoying how the Temporal API, just like nearly all other datetime APIs, has 0 support for querying leap-second information in any shape or form. Suggested workarounds like temporal-tai all require plugging in a leap-second file and keeping it updated, which is especially painful for client-side JS, where you can't just download a leap-second file from someone else's site thanks to the SOP. Meanwhile, browsers update on a cadence more than sufficient to keep an up-to-date copy, but the datetime APIs refuse to expose leap-second info because they're too committed to "only UTC is in-scope for this project".
(The context is that I want to write some JS tools for astronomical calculations, but UTC conversions need leap-second info, so this trend makes it impossible to write something that Just Works™.)
> where you can't just download a leap-second file from someone else's site thanks to the SOP
WDYM by this? Why does the SOP prevent a website from hosting a leap seconds file? All they need to do is set Access-Control-Allow-Origin to allow websites to access it. Or provide it as a JS file—in which case no headers are necessary at all. All the SOP prevents is you hotlinking someone else's leap-seconds file and using their bandwidth without their opt-in.
> Meanwhile, browsers update on a cadence more than sufficient to keep an up-to-date copy
Is this true? I don't know any browser right now that ships with a copy of a leapseconds data file. Adding such a data file and keeping it up to date would probably be a pretty non-trivial task for new browser developers—just for something the browser will never end up using itself. It's not like the ICU/CLDR files where browsers are going to need them anyway for rendering their own user-interface components.
> All they need to do is set Access-Control-Allow-Origin to allow websites to access it. All the SOP prevents is you hotlinking someone else's leap-seconds file and using their bandwidth without their opt-in.
They can, but the major providers (read: the ones I would trust to update it) don't. The IERS doesn't [0], the USNO doesn't [1], IANA doesn't [2], and NIST uses FTP [3]. Keep in mind that these files are constantly being downloaded by various clients for NTP and whatnot, it's not like these providers want to restrict public access, they just don't bother to set the header that would allow JS requests.
> Is this true? I don't know any browser right now that ships with a copy of a leapseconds data file.
From ECMA-262:
> It is required for time zone aware implementations (and recommended for all others) to use the time zone information of the IANA Time Zone Database https://www.iana.org/time-zones/.
Any browser that ships with a copy of tzdb, or knows where to find a copy from the OS, should have access to its leapseconds file. Unless you mean that all of them go solely through ICU and its data files? Which I suppose could be an obstacle unless ICU were to start exposing them.
[0] https://hpiers.obspm.fr/iers/bul/bulc/ntp/leap-seconds.list
[1] https://maia.usno.navy.mil/ser7/tai-utc.dat
[2] https://data.iana.org/time-zones/tzdb/leap-seconds.list
[3] ftp://ftp.boulder.nist.gov/pub/time/leap-seconds.list
> but the datetime APIs refuse to expose leap-second info because they're too committed to "only UTC is in-scope for this project".
This doesn't make sense on at least two different levels.
First, pedantically, the definition of UTC as a time scale is that it includes leap seconds. So if you're committed to UTC, then you're supporting leap seconds.
Second, and to more broadly address your point, you should say, "they're too committed to 'only the POSIX time scale is in-scope for this project.'" That more accurately captures the status quo and also intimates the problem: aside from specialty applications, basically everything is built on POSIX time, which specifically ignores the existence of leap seconds.
Sure, but my gripe isn't even that we ought to change the "POSIX time by default" status quo (the ship has long sailed that everyone counts durations by 'calendar seconds'), it's that the underlying libraries don't even provide enough information for "specialty applications" to reliably correct for it, short of perpetually updating it themselves.
Why should they though? To me it seems like a niche of a niche. I think there is plenty of room for scientific datetime libraries to service this need in a way that is likely better than what a general purpose datetime library would provide. (And indeed, there are many of them.)
I say this as someone who had leap second support working in a pre-release version of Jiff[1] (including reading from leapsecond tzdb data) but ripped it out for reasons.[2]
[1]: https://github.com/BurntSushi/jiff
[2]: https://github.com/BurntSushi/jiff/issues/7
> (including reading from leapsecond tzdb data)
That's part of it: If I were writing a standalone program that could extract info from tzdb or whatever, I'd happily jump through those hoops, and not bother anyone else's libraries. I don't really care about the ergonomics. But for JS scripts in particular, there is no information available that is not provided by either the browser APIs or someone's server. And such servers are not in great supply.
The article is super weird. It never mentions Date.now(). It dances around the subject and exhaustively mentions the equivalent convention for Temporal.
If you want Date to act like Temporal then only use Date.now() as your starting point. It generates the number of milliseconds since 1 Jan 1970. That means the starting output is a number type in integer form. It does not represent a static value, but rather the distance between now and some universal point in the past, a relationship. Yes, Temporal is a more friendly API, but the primary design goal is to represent time as a relational factor.
Then you can format the Date.now() number it into whatever other format you want.
the article has examples of unexpected behavior with timestamps too, so... How do you covert to your desired format without going through Date? Please don't say date-fns
typo:
the second interval should start at 50, not 33we've been using this Temporal polyfill and it's been awesome so far: https://github.com/js-temporal/temporal-polyfill
Note that this is 51kb, it's not exactly lightweight https://bundlephobia.com/package/@js-temporal/polyfill@0.5.1. Still good for forward compatibility or on the server, but for smaller apps it's significant.
Yep, I’ve been using this one which is lighter (20kB): https://github.com/fullcalendar/temporal-polyfill/
How is it compared to moment and especially luxon?
It is a lot more complex than moment, but only because there's a lot of inherent complexity to dates and times that moment just doesn't deal with. So you need to be explicit about whether you're dealing with dates, times, or datetime objects, whether or not the object you're working with has a timezone, etc. Where moment is generally designed to have a convenient API, Temporal is designed to have a correct API.
Didn't moment basically say in so many words, use Temporal?
It’s a web standard api and very small weight. Highly recommend.
I'm really surprised at how Temporal is only just rolling out in Chrome stable.
I would have hoped it'd be ready for wider use by now.
https://caniuse.com/temporal
I suspect that the arrival of ChatGPT caused traffic to the MDN Date API documentation to go down by at least half.
To be fair it's exactly the type of stuff I'd be glad if I never have to think about again.
Go down by half of user traffic, go up 10x of crawler traffic.
Built a scheduler with pretty much all my moment/moment-tz questions answered through ChatGPT. One of the things it excels at, crawling long lived API documentation, answers, etc.
The Date API is fine and relatively normalized. Once you understand it it's very easy to work with. It's biggest problem is that it simply does not support timezones, which is the main reason to use Temporal.
The Date API is horrible
yep. i had a hell of a time building a scheduling system for a business that worked across timezones with the date API
Checking its API, I'm surprised that Temporal.Duration has a constructor with many parameters for years, months, days, ... all the way to nanoseconds, while Temporal.Instant has no way at all to create it given a current year/month/day, only from unix timestamp equivalents (or strings)
That seems to be functionality you'd want to have? Or is the intention you convert your numbers to string first and then back to a Temporal.Instant?
It's perfectly reasonable to default seconds, minutes, hours, etc. to zero in the Duration constructor. But for Instant, it doesn't make sense to default those to zero unless you specify time zone offset.
And indeed, the static method Instant.from does accept an RFC 9557 string, which requires a 2-digit hour and a time zone offset, but can omit minutes and seconds:
Temporal.Instant.from("2026-01-12T00+08:00")
I guess they don’t want people getting confused between local and UTC values for the fields in the constructor (especially as if it took local values it would need to handle DST transitions)
it's because a year/month/date isn't enough to uniquely identify an instant in time. you can create a Temporal.PlainDate(Time) with those values though, then convert to the other types depending on what you need and it needs (e.g. time zone)
So, hold on--the author's soul-breaking complaint isn't all of the "quirks" and inconsistencies with the Date functions, but rather the fact that it's an object? Specifically, an object with mutable properties in a language when all objects have mutable properties?
I mean, the author's conclusion is correct. But I disagree with the rationale. It's like hating an evil dictatorship because they use the wrong font in their propaganda.
> When an immutable value is assigned to a variable, the JavaScript engine creates a copy of that value and stores the copy in memory
Not exactly. The language doesn't specify whether the value is copied or not and, precisely because values are immutable, there's no way for a user to tell if it was or wasn't.
For example, strings are also immutable value types, but you can be certain that no JS engine is fully copying the entire string every time you assign one to a variable or pass it to a parameter.
Somewhat related: Jiff (https://github.com/BurntSushi/jiff) is a Rust library inspired by the Temporal api.
Except Temporal is not, in fact, out.
https://caniuse.com/temporal
The current global availability of native Temporal is 1.81%. For context, IE11(!) has a higher global usage than Temporal has native support. For my organization, this likely means we're years from being able to use Temporal in production, because getting the polyfills approved is such a hassle.
Keep in mind that even as of December last year, Chrome didn't ship with it yet (i.e. support is less than one month old). Safari still does not.
Chrome will ship in 144. It's about to release.
Once Chrome does, for many devs, you can simply enforce a version check and say "please use latest Chrome" and be done with it.
Thankfully temporal-polyfill only depends on temporal-spec. It was pretty easy to get that through.
Good article, but “Java deprecated their Date way back in 1997” is not exactly true. They deprecated a lot of methods and constructors in JDK1.1 when Calendar was introduced, but the class itself was never deprecated and it was the preferred way to represent a point in time until the “modern” approach was provided in java.time in JDK8 (c2014)
Not exactly true, but they deprecated absolutely everything that made it a date. It expresses deep regret in the medium of annotations:
https://javaalmanac.io/jdk/1.2/api/java/util/Date.html
(I can't find the 1.1 docs, but they were the same)
It's one of my favourite examples of how languages pretty much always get date and time hopelessly wrong initially. Java now has one of the best temporal APIs.
Yeah, it effectively became a typed wrapper of a long epoch millis value. Generally treated as immutable by convention in my experience, although of course it technically wasn't as the setters were never removed.
It was hopelessly wrong initially, and got even worse when they added the horrible sql Date/Timestamp/etc classes.
With java.time though, it is the gold standard as far as I've seen.
https://javaalmanac.io/jdk/1.1/api/java.util.Date.html
Curses, I was close. Also: yikes to the design.
related: i had to jump through the Date hoops recently (again) when rewriting uPlot's DST and timezone handling, but i'm pretty happy with the result that avoided much complexity, performance loss, and adding a dependency: https://github.com/leeoniya/uPlot/pull/1072
fun demos: https://leeoniya.github.io/uPlot/demos/timezones-dst.html
Anyone have links that indicate when Safari might have it?
Not yet, adoption is kind of poor atm.
This is not to detract from the quality of the article which is a top-notch introduction to this new API.
Yes, you should use shiny new library instead of the glitchy javascript standard..
Unless you want your website to run in browsers older than a year
Maybe in 10 years we can start using the shiny new thing?
Polyfills are a thing, no?
Late by a decade or more (JSR310 was released in 2014), but still a good development. I've tried convincing colleagues to use js-joda in the past but they thought they were keeping it simple by sticking to moment.js. They weren't.
I remember running into the moment.js issue where my package size doubled by adding a date library: https://github.com/moment/moment/issues/3376
I am not sure if I like mixing value and formatting in single object. On other hand anything will be an improvement compared to that terrible old API.
Temporal objects do not store formatting information. Unless you mean e.g. dropping the time, using a different time zone, etc - but those aren't formatting changes, they logically change the semantics of the data. Just like `myInt += 1` is not changing the "formatting" of `myInt`.
Remember: Date and Temporal objects are logically different things. A Date represents an absolute point in time (a timestamp), while a Temporal object represents a human time (calendar date, clock time, time zone). The fact that Dates are used to represent human time for lack of a better structure is the entire problem statement - the hole that all these other APIs like Temporal try to fill in.
I just groked it before and thought "plain" in `Temporal.PlainDateTime` indicates some specific format instead of just being zoneless. It is actually always using ISO8601 fur build in toString conversions, so I don't really have anything to complain about.
Is Temporal even in though? Last I checked (last year or so), I had to use some bleeding edge version of Firefox to get it, and absolutely nothing else had it. I do agree though it's lovely, and I'd love to see native support for it.
You can always check in "Can I use _?": https://caniuse.com/temporal
It's fully supported as of version 139[0], so since ~June of last year.
[0] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
Seems like the next version(s) of Chrome will have it: https://caniuse.com/temporal
Nope. Only Firefox and Chrome have it, in their latest versions. No Safari or Edge support yet. So this article is a bit premature (unless you use the polyfill.)
> My complaint is about more than parsing or syntax or “developer ergonomics” ... My problem with Date is that using it means deviating from the fundamental nature of time itself.
I don't really have a problem with the substance of this blog post. I have a problem with this exaggerated writing style. It means deviating from the fundamental purpose of writing itself!
I had to scroll all the way to the end to find the actual point, and it was underwhelming.
> Unlike Date, the methods we use to interact with a Temporal object result in new Temporal objects, rather than requiring us to use them in the context of a new instance
Bro, just be honest. This entire blog post was totally about developer ergonomics and that's okay. We all hate the way Date works in javascript.
It's not an exaggeration - you're used to dramatic phrases that use similar wording ("fundamental nature of time itself"), but in this case it's a regular old literally-true statement. Date is used to represent two things: Timestamps and human times (date, time, tz). But it only actually represents the former. Using it to represent the latter is a hack we simply put up with.
bro these ads I can't