People may forget what you did, but they'll remember how you made them feel. It's been years since I've used TS, but I remember it failing to solve about half the problems that I had with JS. I think they did the best they could given the constraints though.
This article is a good example. TS can't fix the underlying APIs, standard library etc.
Meh, I used to have that feeling, especially when discovering fp-ts and then effect (neither of which I've been paid to write), but after about four years, I'm tired of writing it period. The standard library for node is horrible; the ecosystem is okay but not great. And I don't even care for effect anymore. I also write go in my job and it's just okay, but the standard library is much better.
I've been playing around with rust in my free time and like it. I think it's a good FP middle ground. Gleam also looks interesting. But to your point I imagine there aren't many jobs paying for rust and practically none for Gleam.
Agree. While people argue and split hairs over X language is better than Y language (noobs if I’m being honest, even if they have 20 yr experience), one can ship actual products and make money using TS.
It’s a good language that scales quite well to the point where you can then extract specific parts to more performant languages.
99.9% of people won’t have that problem, so I think they should just use TS and solve problems.
Anyone else can be safely ignored and they can complain in the corner.
I'd love to disagree, but every other language's ergonomics just seem so clunky or too magic, whereas with TS and the standard web APIs you have so much room to code how you see fit. Sure, I'd rather a LISP for purity but I'm a realist. If only Brandon Eich had really gotten his way, we'd have Scheme.
Reminding me of the near decade of WAT snark where people thought undefined behaviour was a complete proof of the futility of technology when it was actually just people mistaking what technology is. Like it isn't funny that you can't carry water with a brick but for some reason everyone thought JavaScript should be able to accommodate every possible fuckup with a specific error or just fix it. A nice goal but not something to then feel smug about when it doesn't happen but it seemed to be a viral perspective that persisted for way too long.
People aren't mad that errors aren't fixed automatically, people are mad that the behavior is inconsistent and weird for no fundamental reason other than "that's how the interpreter worked when it all started and it's too late to fix the spec now".
Python is a dynamic language as well and in many ways worse than JS, but
[] + {}
raises a type error.
In JS
[] + {}
is an object and
{} + []
is 0. It's not about being smug, it's that in no way, shape or form that makes any sense.
It's a fun quiz, and there's a lot of surprising behaviour. However in my opinion from a practical perspective it mostly doesn't matter.
Think hard about whether your use case really cares about local time, try and find ways to make instants appropriate. Then stick to UTC ISO 8601 strings / Unix timestamps and most of the complexity goes away, or at least gets contained to a small part of your software.
I know this isn't always possible (I once had to support a feature that required the user took a break covering two periods of 1-5am local, which was obviously fun around DST boundaries) - but in my experience at least the majority of the time you can find ways to minimise the surface area that cares.
If you're passing raw/unvalidated user input to the date parser you're holding it wrong.
Given that the right way to turn user input into validated input is to _parse_ it, passing it to the language feature called the _date parser_ is a completely reasonable thing to do. That this doesn't work probably doesn't surprise javascript programmers much.
Yeah this is a fair take - I guess my unwritten stipulation was don't expect anything from the JavaScript standard library to behave as you'd expect, outside of fairly narrow paths.
TBH even when working with other languages I'd skew towards doing this, possibly because I've worked with JavaScript/TypeScript too much. It's a balance but there's a certain comfort in making constraints really explicit in code you control over blindly trusting the standard library to keep it's behaviour over the lifetime of the product.
Every time someone says "just stick to UTC ISO 8601 strings / Unix timestamp", it's clear they've only worked with dates in very specific ways.
Try that tactic with FUTURE dates.
Meet at 7pm still means meet at 7pm when timezones change, countries make changes to when their summer time starts, etc. Which happens all the time.
And it's actually a more subtle problem. You actually need the context of the timezone in some applications. If your application is showing dinner reservations, for example, you want to display the time in the local time of the restaurant, not the local time of the user. You want to know when it's booked THERE, not where you happen to be right now. I want to know my booking is at 7pm, not 1pm because I happen to be in America right now.
So using GMT/UTC is not a panacea for all the date problems you face.
It's only a solution for dates in the past. And even then you might argue that sometimes it's worth also storing the local time of the user/thing the event happened to, or at the very least the timezone they were in when it happened in a separate field.
> when timezones change, countries make changes to when their summer time starts, etc. Which happens all the time.
The frequency in which time zones are changed surprised me the first time I looked it up. For a single country it's probably quite a big deal that doesn't happen too often. But internationally there are several changes each year. I think it was like 4-6 changes per year in the past decades.
The IANA timezone database does occasionally revise historical rules when relevant information comes to light. So you might have calculated that some historical figure died at such-and-such a time UTC (based on a documented local time), but actually that's inaccurate and you might not know because you haven't redone the calculation with the new rules.
Are any other languages more sane with this stuff? Because I've also been to this particular corner of hell. Also in a web app.
But - wouldn't this be just as horrible in Go or Rust or any other language? (Or god forbid, C?) Are there better timezone APIs in other languages than what you can find in NPM that make these problems any easier to deal with?
> If you're passing raw/unvalidated user input to the date parser you're holding it wrong.
Oh absolutely. But the difference between a sane api and other APIs is that a sane one will fail in a sane way, ideally telling me I’m holding it wrong.
Especially: the key at every turn is to fail hard if there is anything even slightly wrong rather than do something potentially incorrect. Many JS apis seem designed to continue at any cost which is the fundamental problem. You never really want a NaN. You don’t want to coerce strings to [whatever].
I agree with this. I do think it’s an easy trap to fall into if you’re unfamiliar, and hopefully this quiz has made a whole wave of folks more familiar. :)
I agree, and/or give an option to specify the DST offset. That is sometimes useful. I was always confused that Excel did not infer the format when using CSV's though.
"If you're passing raw/unvalidated user input to the date parser you're holding it wrong."
Exactly. I would have never thought about using the Date class in this way. So the behavior is pretty much wtf and local time can get pretty complicated, but I wouldn't expect to get the right time, when passing some vague strings.
The entire point of a parser is to parse unknown values. That's the entire job of a parser: take unstructured (usually string) data and turn it in to something structured, such as a date. If it can't do that reliably with error reporting then it's not a good parser on a very fundamental level.
There are so many valid and reasonable cases where this will bite you.
"Real-world data" from CSV files or XML files or whatnot (that you don't control) and sometimes they have errors in them, and it's useful to know when instead of importing wrong data.
You do something wrong by mistake and getting wrong/confusing behaviour that you literally never want, and then you need to debug where that's coming from.
The user gives you a date, you have no idea what they entered and you want to know if that's correct.
Lots of surprises here! The general theme seems to be that the parser is very eager to find some interpretation of the input as a date, even in ways that appear pretty unprincipled, even in circumstances where human users would probably not agree with the interpretation, and even though it does have ways that it could signal errors. Though maybe some of the weird cases actually do trace back to unusual real-world use cases!
As is usual with these JS critiques, the problem is that you'd never do most of this. Yes, it's silly, but nobody passes random strings into the date constructor because all you really need to know is that the date constructor does weird shit with random strings.
You don't need to burn it, you just need to never rely on the constructor for parsing user input. It all works fine as long as you know the structure of the data before you pass it in.
Yeah this is the curse of the intermediate developer at work
The junior developer experiences nothing but errors, and struggles to get something over the line
The intermediate developer adopts “reduce errors at all cost” mentality and their parsers are too helpful, they make too many assumptions, and you end up with the Date class type behaviour.
The senior developer knows the deadliness of this, and designs a robust class that behaves consistently and errors early on invalid input.
Implementations are ongoing and open source, so you can contribute if you want it to come faster! V8 is currently aiming to use https://github.com/boa-dev/temporal IIRC.
Ha-ha, thanks, I couldn't help but chuckle a bit at that intro. As for them taking their time... Well, yes, it's all rather sad, but I personally came to terms long ago with the snail's pace of JS proposals rolling out. And after all, working with dates and time zones is a rather complex matter in itself, so no judgment here.
I've had to develop interfaces built entirely around date and time operations, and it was painful not so much because of the awful and broken date parsing in JS (although it definitely doesn't help), but rather because of the inherent complexity of how we represent calendar dates and times, and how we build abstractions around these representations. Definitely NOT looking forward to developing that booking system at work...
I'm not sure if I should be pleased or embarrassed about my 17/28. Why do I even know this?
My son was pretty happy with his 11/28 without any experience with js Date. Just deduced it from previous answers. And I explained type coercion to him.
I now realize I may have put him off a career in IT.
It very much is. I put the lil notice at the start that I verified the questions on a specific version of Node, with a specific timezone, because both things matter.
Some notes that I have noticed. First, why does it seem that the V8 date parser is heavily inspired by the Windows date parser (https://devblogs.microsoft.com/oldnewthing/20200304-00/?p=10...)? EDIT: Apparently not, "new Date('Savvyday 29 Oatmeal 94')" is invalid both in Firefox and Chrome.
Second, I opened this in Firefox with the console open to answer these questions, and found these divergences (to summarize, Firefox is strict):
Question 14:
new Date("12.1")
> "12.1" is interpreted as the date December 1st, and as before for dates with no year the default is 2001 because of course.
Firefox returns an Invalid Date object instead.
Question 16:
new Date("12.-1")
> The dash here is ignored, so this is interpreted the same as "12.1".
Again, Firefox returns an Invalid Date object instead.
Question 19:
new Date("maybe 1")
> "may" in "maybe" is parsed as the month May! And for some reason this expression cares about your local timezone, which happens to be BST for me right now.
Seems a broken record, but this is still an Invalid Date for Firefox.
Question 20:
new Date("fourth of may 2010")
> "fourth of" is ignored, this is just parsing "may 2010" and again local timezone is important.
Ibid in Firefox.
Question 21:
new Date("May 4 UTC")
> UTC is correctly parsed as a timezone.
No, Firefox is still not accepting this one.
Question 22:
new Date("May 4 UTC+1")
> You can add modifiers to timezones and it works as you would expect.
Neither this one.
Question 23:
new Date("May 4 UTC+1:59")
> It also supports minutes!
Firefox: Not really.
Final note: It parses Question 24 as you expect in Firefox. Which honestly, it shouldn't!
At the beginning of the quiz, the author noted the exact time zone their laptop is in, have at least one of the questions I got wrong because I didn't take that into account. Totally valid though, and I honestly felt like I should have recognized that it would come into play given how I noticed how specific it was before starting
It’s a mean thing for me to have done, and I did originally have an extra little disclaimer on the questions where it was relevant, but I removed it because it felt like the shock value was more funny.
I use iso strings for dates in JS, because they're such a trap. (As evidenced by even the first few quiz questions here). Moment, a popular alternative, is as bad in many ways. It conflates "date", "time", and "datetime", which causes so much trouble. The explanation I've heard is "time" and "date" shouldn't exist, which is, semantically, incompatible with my experiences.
Yeah a lot of these popular libraries - including Moment, Luxon, Day.js - commit the sin of using a single type of object for distinct concepts. Absolute time, civil time? Basically the same thing right? Just shoehorn them both in.
I can understand why JS' Date is the way it is, but Moment, and even more so Luxon and Day.js, have no excuses - Joda Time has been around since what, 2005?
Always fun to click through JS quizzes for the laughs. I've been programming JS since over a decade, and I never dared to use Date to parse anything I didn't verify with a regex.
i coded security js code for a decade. right when the standard started to get the many updates.
our system was just a really tiny subset of things you could use that worked safely (and predictably) across browsers. even after the updates, we only incorporated was array.filter and structuredcopy. everything else offered no real benefit and only added to the attack surface.
and then came typescript. the biggest missed opportunity in js history.
even today, good js is knowing you can only use 1% of the language, and even that with lot of care
This article is a good example. TS can't fix the underlying APIs, standard library etc.
I've been playing around with rust in my free time and like it. I think it's a good FP middle ground. Gleam also looks interesting. But to your point I imagine there aren't many jobs paying for rust and practically none for Gleam.
It’s a good language that scales quite well to the point where you can then extract specific parts to more performant languages.
99.9% of people won’t have that problem, so I think they should just use TS and solve problems.
Anyone else can be safely ignored and they can complain in the corner.
Python is a dynamic language as well and in many ways worse than JS, but
raises a type error.In JS
is an object and is 0. It's not about being smug, it's that in no way, shape or form that makes any sense.For today's lucky 10,000:
https://www.destroyallsoftware.com/talks/wat (2012)
Think hard about whether your use case really cares about local time, try and find ways to make instants appropriate. Then stick to UTC ISO 8601 strings / Unix timestamps and most of the complexity goes away, or at least gets contained to a small part of your software.
I know this isn't always possible (I once had to support a feature that required the user took a break covering two periods of 1-5am local, which was obviously fun around DST boundaries) - but in my experience at least the majority of the time you can find ways to minimise the surface area that cares.
If you're passing raw/unvalidated user input to the date parser you're holding it wrong.
TBH even when working with other languages I'd skew towards doing this, possibly because I've worked with JavaScript/TypeScript too much. It's a balance but there's a certain comfort in making constraints really explicit in code you control over blindly trusting the standard library to keep it's behaviour over the lifetime of the product.
Try that tactic with FUTURE dates.
Meet at 7pm still means meet at 7pm when timezones change, countries make changes to when their summer time starts, etc. Which happens all the time.
And it's actually a more subtle problem. You actually need the context of the timezone in some applications. If your application is showing dinner reservations, for example, you want to display the time in the local time of the restaurant, not the local time of the user. You want to know when it's booked THERE, not where you happen to be right now. I want to know my booking is at 7pm, not 1pm because I happen to be in America right now.
So using GMT/UTC is not a panacea for all the date problems you face.
It's only a solution for dates in the past. And even then you might argue that sometimes it's worth also storing the local time of the user/thing the event happened to, or at the very least the timezone they were in when it happened in a separate field.
The frequency in which time zones are changed surprised me the first time I looked it up. For a single country it's probably quite a big deal that doesn't happen too often. But internationally there are several changes each year. I think it was like 4-6 changes per year in the past decades.
But - wouldn't this be just as horrible in Go or Rust or any other language? (Or god forbid, C?) Are there better timezone APIs in other languages than what you can find in NPM that make these problems any easier to deal with?
Many European railway timetable amd booking websites fall foul of this.
Oh absolutely. But the difference between a sane api and other APIs is that a sane one will fail in a sane way, ideally telling me I’m holding it wrong.
Especially: the key at every turn is to fail hard if there is anything even slightly wrong rather than do something potentially incorrect. Many JS apis seem designed to continue at any cost which is the fundamental problem. You never really want a NaN. You don’t want to coerce strings to [whatever].
Exactly. I would have never thought about using the Date class in this way. So the behavior is pretty much wtf and local time can get pretty complicated, but I wouldn't expect to get the right time, when passing some vague strings.
There are so many valid and reasonable cases where this will bite you.
"Real-world data" from CSV files or XML files or whatnot (that you don't control) and sometimes they have errors in them, and it's useful to know when instead of importing wrong data.
You do something wrong by mistake and getting wrong/confusing behaviour that you literally never want, and then you need to debug where that's coming from.
The user gives you a date, you have no idea what they entered and you want to know if that's correct.
Burn it and start again.
Good news! The builtin Temporal API is on its way. It's widely regarded as a solid API, learning from some of the best time APIs in other languages.
In terms of parsing, it looks like Temporal only accepts RFC 9557 strings (an extension of ISO 8601 / RFC 3339). Anything else throws an exception.
You don't need to burn it, you just need to never rely on the constructor for parsing user input. It all works fine as long as you know the structure of the data before you pass it in.
Usually I can overcome that urge. It's curious that these designers could not.
The junior developer experiences nothing but errors, and struggles to get something over the line
The intermediate developer adopts “reduce errors at all cost” mentality and their parsers are too helpful, they make too many assumptions, and you end up with the Date class type behaviour.
The senior developer knows the deadliness of this, and designs a robust class that behaves consistently and errors early on invalid input.
Implementations are ongoing and open source, so you can contribute if you want it to come faster! V8 is currently aiming to use https://github.com/boa-dev/temporal IIRC.
I've had to develop interfaces built entirely around date and time operations, and it was painful not so much because of the awful and broken date parsing in JS (although it definitely doesn't help), but rather because of the inherent complexity of how we represent calendar dates and times, and how we build abstractions around these representations. Definitely NOT looking forward to developing that booking system at work...
My son was pretty happy with his 11/28 without any experience with js Date. Just deduced it from previous answers. And I explained type coercion to him.
I now realize I may have put him off a career in IT.
Second, I opened this in Firefox with the console open to answer these questions, and found these divergences (to summarize, Firefox is strict):
Question 14:
> "12.1" is interpreted as the date December 1st, and as before for dates with no year the default is 2001 because of course.Firefox returns an Invalid Date object instead.
Question 16:
> The dash here is ignored, so this is interpreted the same as "12.1".Again, Firefox returns an Invalid Date object instead.
Question 19:
> "may" in "maybe" is parsed as the month May! And for some reason this expression cares about your local timezone, which happens to be BST for me right now.Seems a broken record, but this is still an Invalid Date for Firefox.
Question 20:
> "fourth of" is ignored, this is just parsing "may 2010" and again local timezone is important.Ibid in Firefox.
Question 21:
> UTC is correctly parsed as a timezone.No, Firefox is still not accepting this one.
Question 22:
> You can add modifiers to timezones and it works as you would expect.Neither this one.
Question 23:
> It also supports minutes!Firefox: Not really.
Final note: It parses Question 24 as you expect in Firefox. Which honestly, it shouldn't!
i coded security js code for a decade. right when the standard started to get the many updates.
our system was just a really tiny subset of things you could use that worked safely (and predictably) across browsers. even after the updates, we only incorporated was array.filter and structuredcopy. everything else offered no real benefit and only added to the attack surface.
and then came typescript. the biggest missed opportunity in js history.
even today, good js is knowing you can only use 1% of the language, and even that with lot of care