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.
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.
I’m personally strongly opposed to using any library that becomes a new primitive of my project. I’m fine with an intrusive framework, but never a fundamental change to how plain-old business logic is written. That means fp-ts is out. However stuff like JS’s Date can be replaced under these rules - these days perhaps with a Temporal polyfill.
C# is nominally typed, which, in practice, leads to safer code and less type gymnastics. Of course you can avoid the type gymnastics with "any", then you you're sacrificing safety.
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.
Second, {} + [] isn't a type conversion issue, it's a parsing issue. That {} isn't an object, it's a code block. Assign {} to a variable to ensure it's an object, then do var + [] and you get the same result as the first one.
When using an actual object in both of these, the type conversion makes sense: "+" acts on primitives like strings and numbers, so it has to convert them first. You're getting obj.toString() + array.toString() in either case.
I'll admit the parsing issue here is odd, but most of the time peoples' complaints about javascript type coercion is that they simply never bothered to learn how it works.
One can know the intricacies of how something works and still possess a valid opinion that it doesn't work all that well or defies common sense and expectations.
For me the difference is that you wouldn't then feel compelled to cynically bemoan it for retweets but this schtick went on for years where people would do something out of spec and then complain it was really bizarre to me! Anyway ... Being discouraged by a bug is fine... Making everyone else laugh at the machine on your behalf seems to against understanding and knowledge even if it is fun and funny haha
In the context of the time it was created it was fine to mess with and having an enlightened view from the future can't negate that even though I understand the complaint.
Thanks for posting this. People still don't seem to get that there's no mystery out to make their life difficult and that unfortunately everything can probably ultimately be understood in a deterministic system.
This guy single handedly caused a wave of unproductive cynicism with this stunt. It's like the joke about all the things an everything bagel doesn't have except essentially shitting on the hard work of the entire industry by making up endless nitpicks for laughs.
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!
Of course... they will. Because there are going to be more outdated results on search engines for Date, instead of the Temporal API. But at least there's something positive coming!
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.
It's not just JS. I'm familiar with a language interpreter that used C++ stream I/O for parsing numbers. When C++ expanded the syntax for numbers it broke the interpreter in some cases. This isn't too bad if you catch it quickly but if people start relying on the new, undocumented feature it can be impossible to fix without upsetting someone.
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.
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.
I agree on a theoretical level, but this is javascript and the web we are talking about. Invalid input is rather the norm in genereral, with the expectation the browser should still display something.
But I do dream of a alternative timeline, in where the web evolved different.
Let's say you're setting an appointment. The user puts in nonsense, so you helpfully schedule an appointment for a nonsense date (thank you so much, we'll get right to that in -124 years). Instead of... catching a parsing error and asking the user to try again or something? It's wild that a nonsense date would be considered for any purpose at all in a user-centric system.
If you really ask me, I don't build forms that accept strings as dates from users. There is a date picker element, that can be restricted and validated.
You still need to do some validation of the input because it's difficult to impossible (in many cases) to be absolutely sure the input you receive only comes from your validated form. Even code running entirely within the browser can receive broken/malicious input from an extension, user script, or even the host OS.
It can be a bit belt and suspenders doing validation of specific forms but shit happens. It's much better to catch stuff before it's persisted on the back end or on disk.
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.
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
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!
It's probably improved the past 8 years or so, but I remember Safari was particularly bad for bugs around DST and just dates in general back then, even when using valid input.
We ended up with a bunch of Safari specific workarounds that weren't necessary on Chrome (it was mostly a webview use case so Safari and Chrome were the two we cared about at the time)
Yeah, as I understand it this isn’t backed by any spec. I decided to go with Node’s (v8’s) implementation for the quiz. Fun to see how much divergence there is!
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...
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.
Anyway, after the experience trying to automate something with Google Sheets and wasting 4 hours just to discover that months start at 0 (in the context of parsing string dates and creating Date objects)... yep, no more JS for me.
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
Fix the font for the description field that appears after someone picks an answer. On a normal Windows 10 install, the 0 (zero) is rendered identically to a lowercase o.
If you're going to use fancy fonts at least make them webfonts.
I picked fonts that are present on a wide variety of systems without having to be downloaded on page load. I just forgot some CSS to make sure numbers looked distinct.
Fortunately someone sent me a PR with the right CSS.
The description field uses a typeface that obnoxiously renders 0 (zero) to look like^W^W (upon further investigation: be identical to) lowercase o...
At least on my pretty standard Windows 10 system. No idea which ones of the fonts Avenir, Montserrat, Corbel, URW Gothic, source-sans-pro, sans-serif is being used.
I think it is relevant, it's a part of the standard library. It's one problem that JS has one of the smallest standard libraries, and it's another that the parts it does have just... don't work.
And, "don't use the standard library" is not a solution. Well I mean it is, but it's not free - there's caveats. Which tools do you choose? How do you make sure all your engineers use the same ones? How do you make sure nobody touches the standard library? It's not an easy problem.
Generally true, but the Date and everything around it being absolutely incomprehensible and totally bonkers is very relevant in practice. It's pain to use and triggers billions of bugs daily. It's not an abuse to point out even more wtf about it.
This matches my experience. This is a bit of fun but I’m hoping it has the positive side effect of making people more cautious about how they use Date.
No, it's a proper footgun, same as dereferencing a nullptr in C++. You'll notice that too - doesn't mean it's not a footgun.
And, in fact, most C++ compilers today will actually warn you when you derefernence a nullptr in a stupid, obvious way. Evidently, JS has not caught up to this incredibly sophisticated technology /s.
getYear() returns 125 as it was standard for dates to be offset from 1900 (which led to the Y2K problem). This behaviour should be maintained forever. "Nothing is more important than backwards compatibility"
Or rather, that should be mindset, so that we can achieve at least 90% backwards compatibility in practice.
IIRC it was basically undefined, some data formats were defined. Eventually it was specified that it must correctly parse RFC 3339 and everything was browser defined. I think in the name of web compatibility they have started to carefully define the legacy behaviours of common browsers.
But the morale of this story should be if you need a date from a user user a date input and if you need to parse a computer-readable date always use UNIX timestamps or RFC 3339 (which are correctly and consistently supported).
Since the website says "All questions verified using NodeJS 24.4.0" and that all string parsing made by the Date constructor is define in ECMAScript to follow ISO 8601 plus being engine specific, the sub headline should say: How well do you know V8's Date parsing?
I bet you’re fun at socially coordinated gatherings of individuals convened for the explicit purpose of engaging in recreational, celebratory, or convivial activities, often characterized by the consumption of food and beverages, the enjoyment of music or other entertainments, and the collective participation in structured or unstructured merriment.
Temporal is the language's attempt to fix the issues, instead of relying on 3rd party tools. The current situation forces developers to either choose something supported by the language, which has certain guarantees for backwards compatibility but is awful, and a 3rd party tool, which does not and is not as bad. It seems like the logical resolution is for the language to step up its game, since 3rd party tools have no obligation to be maintained or backwards compatible, or even to remain popular.
I just fixed a bug at work where JS Date was parsing arbitrarily long strings as random date values just because they happened to contain an integer anywhere in the string. Madness.
In a language which doesn't understand that "false" isn't true? I would be entirely unsurprised to discover it's secretly calling a browser vendor web API to search for similarly named dates, or that it's now AI powered and might decide "Last Christmas" means the release date (December 3 1984) of the single not like, Christmas Day in 2024...
I think after the 1970s "Worse is better" languages vanish from the Earth the last shadow of that thinking left might be Javascript, hopefully by then humans aren't writing it but of course for "compatibility" it'll still be implemented by web browsers.
For the same reason dogs aren't the square root of two and justice isn't golf? They're not the same kind of thing at all, if you insist that we should be able to compare them then they're not equal, and since programmers are human and make mistakes probably comparing them is itself a mistake.
You've completely disregarded type system rules of the language, and continue doubling down on your ignorance with ridiculous examples.
> They're not the same kind of thing at all, if you insist that we should be able to compare them then they're not equal, and since programmers are human and make mistakes probably comparing them is itself a mistake.
He's not disregarding the type system rules - everyone knows that JS has a "coerce everything" attitude to types. He's saying it's stupid, and I agree. That was a mistake.
You're saying that the design makes sense because there's a definition, and the definition is what makes it make sense.
There is value in having defined behaviors, but those behaviors can't be immune from criticism. That's letting the tail wag the dog. The purpose of a program is not to execute the rules of the programming language. It's to perform a real and useful task. If those real and useful tasks are complicated because synthetic and arbitrary behaviors of the language exist, then the language is wrong. The tool exists to do work. The work does not exist to provide academic examples for the language.
And, yes, it's possible for it to be impossible to determine a reasonable behavior, but that still doesn't mean we can't have reasonable behavior whenever possible.
> The purpose of a program is not to execute the rules of the programming language. It's to perform a real and useful task. If those real and useful tasks are complicated because synthetic and arbitrary behaviors of the language exist, then the language is wrong. The tool exists to do work. The work does not exist to provide academic examples for the language.
The tasks are not complicated because of this, it literally is default behavior in mainstream languages. And no, they’re neither synthetic, nor arbitrary limitations. The rule is based on types, not on whatever one specific value might mean.
And if they were to define “exceptions”, where do you draw the line?
“F41S3” is this? False? No? What if I’m a l33t h4x0r?
What about 0xF4153? Looks false enough to me.
Again, you are explaining the specifications to defend why the specifications are what they are. That's circular reasoning. Describing the behavior doesn't defend it, and invoking convention doesn't work because different languages have different conventions (which is how we got here).
You know what you do when you can't handle an exceptional case? You throw an exception! Emitting errors is not undesirable behavior! It just means the computer says, "I don't know what to do so I better stop." You're never going to design all possible exceptions away, and that's not a flaw.
The question you should be asking is: why does it ever make sense to silently compare a character string to anything other than a character string? Semanticly, it's nonsense to compare different types. The only way you can do it is when the other type has a canonical string representation, neverminding issues of culture or language.
This is why, for example, C# has String.IsNullOrWhitespace() and String.IsNullOrEmpty(). It's partly to cover common combinations, but also to idiomatically determine if a meaningful value is present, which is what `StringVal == True` and `if (StringVal)` are trying to express and failing at.
A little bit of truthiness seems like a good idea at first. You decide to treat empty strings and undefined as falsy and it feels good, so you go ahead and start treating zero as falsy too.
And then all of a sudden code that is expecting to get an array or undefined gets handed a zero or an empty string because someone called it with
x && [x]
Or
x.length && x
And that’s how you end up with a zero showing up on a webpage instead of a list of to-do items when the list is empty.
What does "useful" mean here? Useful the way it'd be useful if butter knives could also cut trees down more easily or if hats were also televisions - ie more uses = more useful?
Programming languages aren't for the machine, they're for humans, and humans make mistakes so we need to design the language with that in mind. "Truthiness" is a footgun, it increases the chance you'll write something you did not mean without even realising.
yea that's an odd example to pick. expecting type conversion to add meaning to strings is a programmer problem not a language problem. really comes down to developers not thinking about types and their meaning anymore.
there are plenty of javascript examples that are actually weird though, especiall when javascript DOES apply meaning to strings, e.g. when attempting implicit integer parsing.
It’s the _existence_ of an implicit conversion from string to boolean that the parent is pointing out as a problem, not how it’s implemented. But that’s Jãvascript bb
Maybe I’m missing the example but can you not check the truthiness of strings in basically any high level language? At least python does it the same way and it’s very useful.
The point is that this is a well-defined (not pun intended) behavior that exists within C, C++, Python, Ruby and probably a handful more popular languages. This set pretty much constitutes like 70%(?) of mainstream languages. Yet only JS gets shit thrown its way in this thread.
Please don't make fun of JavaScript. Last time it happened, it replied with Node and now it's everywhere.
I maintain that TypeScript is probably the best language you’ll be able to get paid to write.
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.
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.
I’m personally strongly opposed to using any library that becomes a new primitive of my project. I’m fine with an intrusive framework, but never a fundamental change to how plain-old business logic is written. That means fp-ts is out. However stuff like JS’s Date can be replaced under these rules - these days perhaps with a Temporal polyfill.
C# pays fine
If you like one, you’ll prolly like the other
Hell you might even like ActionScript ;P
C# is nominally typed, which, in practice, leads to safer code and less type gymnastics. Of course you can avoid the type gymnastics with "any", then you you're sacrificing safety.
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.First, [] + {} isn't an object, it's a string.
Second, {} + [] isn't a type conversion issue, it's a parsing issue. That {} isn't an object, it's a code block. Assign {} to a variable to ensure it's an object, then do var + [] and you get the same result as the first one.
When using an actual object in both of these, the type conversion makes sense: "+" acts on primitives like strings and numbers, so it has to convert them first. You're getting obj.toString() + array.toString() in either case.
I'll admit the parsing issue here is odd, but most of the time peoples' complaints about javascript type coercion is that they simply never bothered to learn how it works.
One can know the intricacies of how something works and still possess a valid opinion that it doesn't work all that well or defies common sense and expectations.
For me the difference is that you wouldn't then feel compelled to cynically bemoan it for retweets but this schtick went on for years where people would do something out of spec and then complain it was really bizarre to me! Anyway ... Being discouraged by a bug is fine... Making everyone else laugh at the machine on your behalf seems to against understanding and knowledge even if it is fun and funny haha
The complaint is that type coercion exists at all. It solves no problems and creates several out of thin air.
Or are you arguing that ceteris paribus you'd rather not have the language throw an error or just propagate undefined?
In the context of the time it was created it was fine to mess with and having an enlightened view from the future can't negate that even though I understand the complaint.
Thanks for posting this. People still don't seem to get that there's no mystery out to make their life difficult and that unfortunately everything can probably ultimately be understood in a deterministic system.
I've read your comment several times and I still don't get how I'm supposed to be frustrated by this?
> the near decade of WAT snark
For today's lucky 10,000:
https://www.destroyallsoftware.com/talks/wat (2012)
This guy single handedly caused a wave of unproductive cynicism with this stunt. It's like the joke about all the things an everything bagel doesn't have except essentially shitting on the hard work of the entire industry by making up endless nitpicks for laughs.
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!
The problem is that you couldn’t start to guess all of these. It’s just random noise. Strings 32-49 are in the 2000s but 50 onwards are in the 1900.
Burn it and start again.
> 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.
Bad news: shitty designed parts are here to stay, because people will cry for backwards compatibility.
Sure. But people don't have to keep using them.
Of course... they will. Because there are going to be more outdated results on search engines for Date, instead of the Temporal API. But at least there's something positive coming!
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.
It's not just JS. I'm familiar with a language interpreter that used C++ stream I/O for parsing numbers. When C++ expanded the syntax for numbers it broke the interpreter in some cases. This isn't too bad if you catch it quickly but if people start relying on the new, undocumented feature it can be impossible to fix without upsetting someone.
[Small edits for clarity.]
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.
> you want to display the time in the local time of the restaurant
Many European railway timetable amd booking websites fall foul of this.
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.
A parser is supposed to reject invalid input, not generate semi-arbitrary outputs.
I agree on a theoretical level, but this is javascript and the web we are talking about. Invalid input is rather the norm in genereral, with the expectation the browser should still display something.
But I do dream of a alternative timeline, in where the web evolved different.
Let's say you're setting an appointment. The user puts in nonsense, so you helpfully schedule an appointment for a nonsense date (thank you so much, we'll get right to that in -124 years). Instead of... catching a parsing error and asking the user to try again or something? It's wild that a nonsense date would be considered for any purpose at all in a user-centric system.
If you really ask me, I don't build forms that accept strings as dates from users. There is a date picker element, that can be restricted and validated.
You still need to do some validation of the input because it's difficult to impossible (in many cases) to be absolutely sure the input you receive only comes from your validated form. Even code running entirely within the browser can receive broken/malicious input from an extension, user script, or even the host OS.
It can be a bit belt and suspenders doing validation of specific forms but shit happens. It's much better to catch stuff before it's persisted on the back end or on disk.
Then again, I don’t think you pass user input directly into a date constructor in any language, in practice.
You decide on the format that makes sense for the user, you validate the input against that format, and then you map it into a native date.
If the date constructor supports the format you want, it’s only coincidence that makes that final mapping step simpler.
So, the native date constructor having weird behavior on invalid strings doesn’t really change real world code.
Good luck with a random dependency or dependency of a dependency that doesn’t work that way.
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.
10/28. Not bad. But probably also is implementation dependent: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
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
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.
Javascript put me off a career in IT for 20 years, and even today I still avoid it like radioactive waste.
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:
> "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!
It's probably improved the past 8 years or so, but I remember Safari was particularly bad for bugs around DST and just dates in general back then, even when using valid input.
We ended up with a bunch of Safari specific workarounds that weren't necessary on Chrome (it was mostly a webview use case so Safari and Chrome were the two we cared about at the time)
Assumingly to me this was around the same time that Apple seemed to have DST problems more generally, such as their iOS alarm clock mishap https://www.theguardian.com/technology/blog/2010/nov/01/ipho...
A quick test of Vivaldi with some of those shows it nowhere near as strict as your Firefox is. Amusingly
is an invalid date, whereas all three of are valid but in British Summer Time.Yeah, as I understand it this isn’t backed by any spec. I decided to go with Node’s (v8’s) implementation for the quiz. Fun to see how much divergence there is!
Scored 17/28. Thank you, this is absolutely cursed! It's probably a good time to go and check out the Temporal stuff (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...).
They're certainly taking their sweet time with it. Reading the last progress update is mildly entertaining though: https://github.com/tc39/notes/blob/HEAD/meetings/2024-07/jul...
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...
That's not the last progress update. Most recent is https://github.com/tc39/notes/blob/d5b5db6969359fad11b6898b7....
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 scored what I have to assume is November 28, 2000.
I got a good laugh out of this.
4 / 28 "You would have scored higher by guessing at random."
I think my strategy for JavaScript going forward is to 'drop & run'.
Same here! Too bad... I did guess at random! :D
Anyway, after the experience trying to automate something with Google Sheets and wasting 4 hours just to discover that months start at 0 (in the context of parsing string dates and creating Date objects)... yep, no more JS for me.
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.
so true.
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
And now you have two problems
JavaScript’s Date class is a fairly straight port from Java, including most of the WAT in this quiz https://docs.oracle.com/en/java/javase/21/docs/api/java.base...
Post by the author Sam Rose about it: https://bsky.app/profile/samwho.dev/post/3ltpdkr3bmk2o
It me.
Fix the font for the description field that appears after someone picks an answer. On a normal Windows 10 install, the 0 (zero) is rendered identically to a lowercase o.
If you're going to use fancy fonts at least make them webfonts.
This should be fixed.
I picked fonts that are present on a wide variety of systems without having to be downloaded on page load. I just forgot some CSS to make sure numbers looked distinct.
Fortunately someone sent me a PR with the right CSS.
Good job Sam! Been a while since we spoke on Twitter, but good to see you here :)
Dangit I’m not recognising your username, sorry!
Oh hi! Thanks for the great quiz
You’re welcome!
So... any browser other than Firefox feel like shipping Temporal yet?
12/28, could've gotten a few more by thinking harder, but I was getting so annoyed that I didn't want to, great job!
The description field uses a typeface that obnoxiously renders 0 (zero) to look like^W^W (upon further investigation: be identical to) lowercase o...
At least on my pretty standard Windows 10 system. No idea which ones of the fonts Avenir, Montserrat, Corbel, URW Gothic, source-sans-pro, sans-serif is being used.
This should be fixed. Sorry about that.
What I have learned is that "new Date(...)" never throws errors, and you would have to do something like "new Date(...).toISOString()".
Cool.
The first set of questions are logical and make some sense. But then there come questions asking you similar but with slightly different values.
And that’s when everything stops making sense.
Cute. But things like these have tendency to be abused by “haha, js” crowd even if those things are irrelevant in practice.
I think it is relevant, it's a part of the standard library. It's one problem that JS has one of the smallest standard libraries, and it's another that the parts it does have just... don't work.
And, "don't use the standard library" is not a solution. Well I mean it is, but it's not free - there's caveats. Which tools do you choose? How do you make sure all your engineers use the same ones? How do you make sure nobody touches the standard library? It's not an easy problem.
Generally true, but the Date and everything around it being absolutely incomprehensible and totally bonkers is very relevant in practice. It's pain to use and triggers billions of bugs daily. It's not an abuse to point out even more wtf about it.
This matches my experience. This is a bit of fun but I’m hoping it has the positive side effect of making people more cautious about how they use Date.
date.getYear() => 125
If that’s not relevant, I don’t know what is.
> date.getFullYear() => 2025
`getYear` is literally deprecated everywhere and is not part of the spec.
https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec...
Right, but it exists and looks correct and runs and won’t trigger any kind of error if you write code that uses it.
This is what we call a ‘foot gun’.
On the other hand, you notice it the second you go use the software you just wrote to ensure it works.
So it’s more like a foot dollar store water gun.
No, it's a proper footgun, same as dereferencing a nullptr in C++. You'll notice that too - doesn't mean it's not a footgun.
And, in fact, most C++ compilers today will actually warn you when you derefernence a nullptr in a stupid, obvious way. Evidently, JS has not caught up to this incredibly sophisticated technology /s.
Today you should use getFullYear() => 2025
getYear() returns 125 as it was standard for dates to be offset from 1900 (which led to the Y2K problem). This behaviour should be maintained forever. "Nothing is more important than backwards compatibility"
Or rather, that should be mindset, so that we can achieve at least 90% backwards compatibility in practice.
Yes, a language that was created in 1995 was entirely justified in adopting a convention that would break within five years.
Another thing is with timezone: https://github.com/date-fns/tz/issues/57
I'm not sure if it's caused by JavaScript quirkiness under the hood or a bug in the library, but it's mindblowing.
And don’t forget that Date objects are mutable!
See also: "Falsehoods programmers believe about time and time zones":
https://news.ycombinator.com/item?id=11515125
I'm curious how would a formal spec define those behaviors.
IIRC it was basically undefined, some data formats were defined. Eventually it was specified that it must correctly parse RFC 3339 and everything was browser defined. I think in the name of web compatibility they have started to carefully define the legacy behaviours of common browsers.
But the morale of this story should be if you need a date from a user user a date input and if you need to parse a computer-readable date always use UNIX timestamps or RFC 3339 (which are correctly and consistently supported).
It's one of the [incorrect] answers to these questions: "Throws an error".
Lots of lessons in language design here. No explicit error return type and null bottom type create high ambiguity in such edge cases.
This is one of the reasons that I, an amateur dev, never touch dates other than via date-fns or other date libs.
Dates and times are insane, no matter the language.
I found that too painful to get further than #14
I gave up on like 5 and I'm a JS developer. Who dreamed this API up?
9/28 - This was very good fun. Can't believe so much of the world's (important?) software is written in this toy language.
28 reasons to not use the built-in Date class
someone should make one for Python based on https://github.com/satwikkansal/wtfpython
Related: https://www.destroyallsoftware.com/talks/wat
Since the website says "All questions verified using NodeJS 24.4.0" and that all string parsing made by the Date constructor is define in ECMAScript to follow ISO 8601 plus being engine specific, the sub headline should say: How well do you know V8's Date parsing?
I bet you’re fun at socially coordinated gatherings of individuals convened for the explicit purpose of engaging in recreational, celebratory, or convivial activities, often characterized by the consumption of food and beverages, the enjoyment of music or other entertainments, and the collective participation in structured or unstructured merriment.
JavaScript is hilarious through and through.
JavaScript has survived because it must be backwards compatible, not because it ever made sense.
Adding Temporal will only add to the chaos. Now there will be Date, moment, Luxon’s objects, and Temporal. See??? We fixed it!!!
Temporal is the language's attempt to fix the issues, instead of relying on 3rd party tools. The current situation forces developers to either choose something supported by the language, which has certain guarantees for backwards compatibility but is awful, and a 3rd party tool, which does not and is not as bad. It seems like the logical resolution is for the language to step up its game, since 3rd party tools have no obligation to be maintained or backwards compatible, or even to remain popular.
Too many standards? Time to add another one. This one will be final, I promise.
I just fixed a bug at work where JS Date was parsing arbitrarily long strings as random date values just because they happened to contain an integer anywhere in the string. Madness.
Haha that was fun :D
Thanks!
Why?
I discovered the 0/“0” disparity in work this week for the first time. Then I tried “1” and “2” and knew there was fun to be had. :)
But who came up with such a confusing „logic“?
„0“ and „1“ are for years, everything above are month.
Does the text parsing only work for English or other languages too?
10 / 28 lol, that's sad
[dead]
In a language which doesn't understand that "false" isn't true? I would be entirely unsurprised to discover it's secretly calling a browser vendor web API to search for similarly named dates, or that it's now AI powered and might decide "Last Christmas" means the release date (December 3 1984) of the single not like, Christmas Day in 2024...
I think after the 1970s "Worse is better" languages vanish from the Earth the last shadow of that thinking left might be Javascript, hopefully by then humans aren't writing it but of course for "compatibility" it'll still be implemented by web browsers.
Why wouldn’t “false” be true? It’s a non-empty string.
For the same reason dogs aren't the square root of two and justice isn't golf? They're not the same kind of thing at all, if you insist that we should be able to compare them then they're not equal, and since programmers are human and make mistakes probably comparing them is itself a mistake.
You've completely disregarded type system rules of the language, and continue doubling down on your ignorance with ridiculous examples.
> They're not the same kind of thing at all, if you insist that we should be able to compare them then they're not equal, and since programmers are human and make mistakes probably comparing them is itself a mistake.
It is literally encoded in the spec.
https://262.ecma-international.org/13.0/#sec-toboolean
He's not disregarding the type system rules - everyone knows that JS has a "coerce everything" attitude to types. He's saying it's stupid, and I agree. That was a mistake.
This reasoning is essentially circular.
You're saying that the design makes sense because there's a definition, and the definition is what makes it make sense.
There is value in having defined behaviors, but those behaviors can't be immune from criticism. That's letting the tail wag the dog. The purpose of a program is not to execute the rules of the programming language. It's to perform a real and useful task. If those real and useful tasks are complicated because synthetic and arbitrary behaviors of the language exist, then the language is wrong. The tool exists to do work. The work does not exist to provide academic examples for the language.
And, yes, it's possible for it to be impossible to determine a reasonable behavior, but that still doesn't mean we can't have reasonable behavior whenever possible.
> The purpose of a program is not to execute the rules of the programming language. It's to perform a real and useful task. If those real and useful tasks are complicated because synthetic and arbitrary behaviors of the language exist, then the language is wrong. The tool exists to do work. The work does not exist to provide academic examples for the language.
The tasks are not complicated because of this, it literally is default behavior in mainstream languages. And no, they’re neither synthetic, nor arbitrary limitations. The rule is based on types, not on whatever one specific value might mean.
And if they were to define “exceptions”, where do you draw the line?
“F41S3” is this? False? No? What if I’m a l33t h4x0r? What about 0xF4153? Looks false enough to me.
Again, you are explaining the specifications to defend why the specifications are what they are. That's circular reasoning. Describing the behavior doesn't defend it, and invoking convention doesn't work because different languages have different conventions (which is how we got here).
You know what you do when you can't handle an exceptional case? You throw an exception! Emitting errors is not undesirable behavior! It just means the computer says, "I don't know what to do so I better stop." You're never going to design all possible exceptions away, and that's not a flaw.
The question you should be asking is: why does it ever make sense to silently compare a character string to anything other than a character string? Semanticly, it's nonsense to compare different types. The only way you can do it is when the other type has a canonical string representation, neverminding issues of culture or language.
This is why, for example, C# has String.IsNullOrWhitespace() and String.IsNullOrEmpty(). It's partly to cover common combinations, but also to idiomatically determine if a meaningful value is present, which is what `StringVal == True` and `if (StringVal)` are trying to express and failing at.
But it shouldn’t be
So what should be the value of `"false" == true`?
undefined or TypeError would be suitable.
So shall we require checking for matching type of first? It doesn't seem like an improvement to me.
Should "falsch", "faux" and "ЛОЖЬ" be understood as false too?
Not at all, "false" shouldn't be false either, the appropriate thing to do when the programmer writes nonsense is to reject what they wrote entirely.
What a conventional wisdom for 30 year old language that is based on whatever state of the art was at the time.
They should’ve just deprecated it right away, invent Time Machine, move to the future, grab Rust and make it the scripting language. Duh.
You don‘t think being able to check the truthiness of strings is a useful thing?
A little bit of truthiness seems like a good idea at first. You decide to treat empty strings and undefined as falsy and it feels good, so you go ahead and start treating zero as falsy too.
And then all of a sudden code that is expecting to get an array or undefined gets handed a zero or an empty string because someone called it with
Or And that’s how you end up with a zero showing up on a webpage instead of a list of to-do items when the list is empty.What does "useful" mean here? Useful the way it'd be useful if butter knives could also cut trees down more easily or if hats were also televisions - ie more uses = more useful?
Programming languages aren't for the machine, they're for humans, and humans make mistakes so we need to design the language with that in mind. "Truthiness" is a footgun, it increases the chance you'll write something you did not mean without even realising.
yea that's an odd example to pick. expecting type conversion to add meaning to strings is a programmer problem not a language problem. really comes down to developers not thinking about types and their meaning anymore.
there are plenty of javascript examples that are actually weird though, especiall when javascript DOES apply meaning to strings, e.g. when attempting implicit integer parsing.
It’s the _existence_ of an implicit conversion from string to boolean that the parent is pointing out as a problem, not how it’s implemented. But that’s Jãvascript bb
Maybe I’m missing the example but can you not check the truthiness of strings in basically any high level language? At least python does it the same way and it’s very useful.
edit: I'm mostly wrong here.
Because "0" is false. In a logical world, a non-empty string being truthy is fine even if the value is "false". Javascript isn't logical.
``` > if ("0") console.log("true");
true ```
Excuse me?
> In a logical world, a non-empty string being truthy is fine even if the value is "false". Javascript isn't logical.
You must hate our illogical world built on C, because it has the same behavior.
Appealing to C - the land of undefined behavior - as a paragon of logic seems like a strange authority to reach for.
The point is that this is a well-defined (not pun intended) behavior that exists within C, C++, Python, Ruby and probably a handful more popular languages. This set pretty much constitutes like 70%(?) of mainstream languages. Yet only JS gets shit thrown its way in this thread.
I did a `"0" == false` which returned true. I may need another cup of coffee before making claims.
Are you crazy? Which language does? I can only think of markup languages that do.
Should "0" also === 0? How about "{}" === {}? When does it stop?
What do you mean? false isn’t true in JavaScript.
“false”, not false. So there’s odd type coercion, but the problem is that it can happen without you asking for it.
Python does the same thing. I don’t like it there either, but at least it’s more consistent about it.
Yes strings aren’t false unless they’re empty. Good thing.
Or, judging by other comments, “0”.
The string with the value of "false" evaluates to true.
In other words
If ("false") { /* You will be here */ }