New Date("wtf") – How well do you know JavaScript's Date class?

409 pointsposted 7 months ago
by OuterVale

202 Comments

pluc

7 months ago

Please don't make fun of JavaScript. Last time it happened, it replied with Node and now it's everywhere.

teaearlgraycold

7 months ago

I maintain that TypeScript is probably the best language you’ll be able to get paid to write.

andai

7 months ago

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.

teaearlgraycold

7 months ago

I wouldn’t blame TS for not fixing the JS standard library. It’s just a type system.

Atotalnoob

7 months ago

Normally, I would agree with you, but if you are going to say it’s the best language, then the criticism is fair.

Best language would be the entire ecosystem, including standard library

teaearlgraycold

7 months ago

Yes, I just think you’ve got the wrong expectations if you say “TS failed to fix half of JS’s” problems.

bspammer

7 months ago

Kotlin and even modern Java are both preferable for me. There’s no shortage of JVM roles.

teaearlgraycold

7 months ago

If your entire stack is using optionals then Java can be acceptable. It’s not a terrible language otherwise. Checked exceptions are a failure IMO because they only check for some types of errors.

t-writescode

7 months ago

As of the last couple years, you're probably not wrong. Basically every open role right now requires TypeScript, Node, Next.JS, etc.

frizlab

7 months ago

Swift is a bliss to write and easy to get paid to write it.

dsego

7 months ago

I feel differently, but I've only tried it briefly. It feels like an abomination that can't decide what it is and has just too much syntactic sugar.

wiseowise

7 months ago

Atrocious tooling.

agos

7 months ago

I love Swift as in the language, the syntax, the theory. I despise just as much its tooling that has led me to infuriating moments such as finding out that ternary operators where the cause for a ballooning compilation time.

nialv7

7 months ago

i was paid to write rust for a couple of years.

AceJohnny2

7 months ago

was it for blockchain stuff

nialv7

7 months ago

Actually nope :)

cjbgkagh

7 months ago

Hence the 'probably'

douglasisshiny

7 months ago

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.

teaearlgraycold

7 months ago

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.

stephenlf

7 months ago

I believe Fly.io deploys some Gleam in prod. I tried playing with Gleam for a bit, but I got stuck trying to make the Actor Model make sense. It’s Gleam’s solution to mutable state, inherited from Erlang and the BEAM. It takes so much code just to emulate a simple, mutable Map. I liked Rust’s middle ground with `mut` in function defs.

user

7 months ago

[deleted]

suprfnk

7 months ago

C# pays fine

mock-possum

7 months ago

If you like one, you’ll prolly like the other

Hell you might even like ActionScript ;P

DonHopkins

7 months ago

If you like TypeScript and C#, then you'll probably also like Delphi and Turbo Pascal!

They were all written by the same guy, Anders Hejlsberg:

https://en.wikipedia.org/wiki/Anders_Hejlsberg

https://news.ycombinator.com/item?id=19568681

"My favorite is always the billion dollar mistake of having null in the language. And since JavaScript has both null and undefined, it's the two billion dollar mistake." -Anders Hejlsberg

"It is by far the most problematic part of language design. And it's a single value that -- ha ha ha ha -- that if only that wasn't there, imagine all the problems we wouldn't have, right? If type systems were designed that way. And some type systems are, and some type systems are getting there, but boy, trying to retrofit that on top of a type system that has null in the first place is quite an undertaking." -Anders Hejlsberg

dotancohen

7 months ago

  > "My favorite is always the billion dollar mistake of having null in the language. And since JavaScript has both null and undefined, it's the two billion dollar mistake."
  > -Anders Hejlsberg
Why can't all-1s be null? E.g. a small int goes from the range 0-255 to the range 0-254, but we get a really useful property with no out-of-band Nullable overhead.

With signed ints it even leads to symmetric ranges in the negative and positive directions.

DonHopkins

7 months ago

The FORTH-83 standard changed FIG-FORTH's official value of TRUE from 1 to -1 so all its bits were set. That was a rough transition like Python 2=>3, but worth it. It also defined /MOD integer division to be floored (rounded towards -infinity instead of zero like FIG-FORTH), which was also a tough change but the right one, especially for graphics.

https://python-history.blogspot.com/2010/08/why-pythons-inte...

https://forth-standard.org/standard/diff?utm_source=chatgpt....

https://atariwiki.org/wiki/Wiki.jsp?page=Converting+FIG-Fort...

>4. For various reasons the definition of all divide functions general effect is that quotients are floored instead of rounded toward zero. This should cause no problems for most pre-existing application software. The new divide functions are marginally slower than the old (a few machine cycles under most circumstances). The side-effects of the redefinition for floored divide can be counter-intuitive under some circumstances. For example, in FIG-Forth the operation

      -40 360 MOD
>would return the obvious answer (-40) on the stack, while 83- Standard Forth will return the answer 320!

>5. The true flag returned by all logical operations has been changed from the value 1 (in FIG-Forth) to the value -1 (in Forth-83, all bits set). If your code used the 0 or 1 returned by a comparison in an arithmetic operation, you will need to interpolate the operator ABS after the logical operator. This is a particularly difficult problem to look for in your source code. However, we feel that this mutation in the 83-Standard was beneficial as it allows the returned true/false value to be used as a mask for AND.

dotancohen

7 months ago

Hello Don!

I always suspected that FORTH had inconsistencies in division across versions. That's why the lord told us to Go FORTH and Multiply instead.

oldsecondhand

7 months ago

Delphi has been dead for 10+ years. Nobody uses it except for a few legacy applications and licenses cost $1200+.

DonHopkins

7 months ago

You're kind of missing the point. Turbo Pascal has been dead for a lot longer. Or is it?

The point is that TypeScript and C# are extremely similar for a good reason, not a coincidence, and that Anders Hejlsberg knows what the fuck he's doing and talking about, and has been implementing amazing groundbreaking well designed languages and IDEs for a very long time. Turbo Pascal was so great it flummoxed Bill Gates, so Microsoft sent a limo to recruit and hire Anders Hejlsberg from Borland, then he made Visual J++, Windows Foundation Classes, C#, and TypeScript.

https://en.wikipedia.org/wiki/Turbo_Pascal

>Scott MacGregor of Microsoft said that Bill Gates "couldn't understand why our stuff was so slow" compared to Turbo Pascal. "He would bring in poor Greg Whitten [programming director of Microsoft languages] and yell at him for half an hour" because their company was unable to defeat Kahn's small startup, MacGregor recalled.

https://news.ycombinator.com/item?id=8664370

>"According to the suit, Microsoft also offered Mr. Hejlsberg a $1.5 million signing bonus, a base salary of $150,000 to $200,000 and options for 75,000 shares of Microsoft stock. After Borland's counteroffer last October, Microsoft offered another $1.5 million bonus, the complaint says."

const_cast

7 months ago

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.

moomoo11

7 months ago

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.

soulofmischief

7 months ago

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.

th0ma5

7 months ago

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.

qsort

7 months ago

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.

Izkata

7 months ago

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.

otterley

7 months ago

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.

th0ma5

7 months ago

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

dcow

7 months ago

It’s absurd. Comedy is cognitive dissonance manifest. It can’t not be funny.

th0ma5

7 months ago

I don't have dissonance. The language has the features that were designed or there is a bug in what they intended and I don't know why you think adding two empty objects together should make sense anyway. That it doesn't work resolves the dissonance.

qsort

7 months ago

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?

th0ma5

7 months ago

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.

shakna

7 months ago

JS has had how many breaking changes since then...? They've transitioned to the future.

Why is it still here today?

josephg

7 months ago

> JS has had how many breaking changes since then...?

What breaking changes has JS ever had? Its an incredibly stable language.

shakna

7 months ago

Ok, lets reword that. JS has breaking changes in browsers or node at least once a year.

If the platform can continuously shift, in an ecosystem that rots faster than my veggie garden, can we not have more sensible systems in place?

josephg

7 months ago

You’ve still failed to give any examples of these breaking changes. Old websites still work great.

I’ll try again. What breaking changes does JavaScript make? What are you talking about?

shakna

7 months ago

8 months ago, Chrome rewrote how URLs work [0]. Which, unsurprisingly, affects the `URL` constructor in JS.

We have had so many APIs vanish from any context to "secure contexts" only. Like AppCache, or workers, or the clipboard.

Entire APIs like XMLHttpRequestProgressEvent have vanished entirely.

In fact, there is a lot of obsolete features. Enough that there's a list. [1] You can't use global or source with a RegExp anymore. You can't use the arity property on a function anymore. `Object.prototype.eval` is dead. `Object.getNotifier` is dead. `Date.prototype.toLocaleFormat()` is dead.

Old websites have been broken. Repeatedly. Or we wouldn't have, say, blogspam on why mixed content suddenly broke some Wordpress systems.

Yes, these are good changes. They're more secure. However, we're willing to break some sites in the name of security, but unwilling to fix ambiguous parsing for the programmer?

[0] https://news.ycombinator.com/item?id=41912354

[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...

twelve40

7 months ago

> peoples' complaints about javascript type coercion is that they simply never bothered to learn how it works

soo.... if the pesky people keep complaining, maybe it really doesn't make any sense? i for the life of me could never figure out why a bunch of mainstream languages a couple of decades ago decided that typing is no longer necessary and should be abolished. Is there any benefit of removing type checking (and relying on bizarre implicit coercion rules when ambiguity ensues)?

dcow

7 months ago

You will never bother me to learn something as convoluted as {} being sometimes parsed as an object and sometimes as a code block.

user

7 months ago

[deleted]

th0ma5

7 months ago

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.

th0ma5

7 months ago

I've read your comment several times and I still don't get how I'm supposed to be frustrated by this?

fragmede

7 months ago

> the near decade of WAT snark

For today's lucky 10,000:

https://www.destroyallsoftware.com/talks/wat (2012)

th0ma5

7 months ago

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.

dcow

7 months ago

Did you even read TFA? Tell me dates make even the faintest sense.

hnbad

7 months ago

`Date` is based on the original Java `Date` class and its API was mostly copied verbatim, explaining a lot of the quirks and silliness. While JS can't remove things easily because that would break the web, a lot of work has gone into a set of time primitives that will effectively replace it. `Date`'s parsing logic is so bad even Java has deprecated it.

This is one of those cases where the problem isn't language design but boardroom politics - Sun wanted JS not to compete with Java so they had to try to make JS more like Java to present JS as a kind of "Java for amateurs".

mnahkies

7 months ago

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.

JonChesterfield

7 months ago

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.

mnahkies

7 months ago

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.

masfuerte

7 months ago

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.]

mattmanser

7 months ago

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.

kapep

7 months ago

> 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.

NoInkling

7 months ago

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.

josephg

7 months ago

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?

taylorlunt

7 months ago

Elixir handles all of this pretty well, for example differentiating between Date, Time, NaiveDateTime (a date and time), and DateTime (a date and time in a particular timezone). The Timex library is a great improvement too.

JS has libraries that make the problem easier too. Though you'll never find a magic library that makes all the complexity disappear, because at the end of the day, you do need to tell the computer whether you mean 7 pm on the wall clock of where the users happen to be, 7 pm on a specific date in a specific time zone, etc. and doing math between dates is inherently complex with e.g. daylight savings changes. You might end up creating a datetime that doesn't exist (which Elixir handles well).

dingi

7 months ago

Well, Java's date time APIs are pretty good if not best in the industry.

whatevaa

7 months ago

Databases like postgres need timezone stored separately anyway, so for scheduling store local time and time zone it was scheduled in separately.

gpvos

7 months ago

> you want to display the time in the local time of the restaurant

Many European railway timetable amd booking websites fall foul of this.

alkonaut

7 months ago

> 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].

samwho

7 months ago

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. :)

Hilift

7 months ago

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.

lukan

7 months ago

"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.

arp242

7 months ago

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.

colonwqbang

7 months ago

A parser is supposed to reject invalid input, not generate semi-arbitrary outputs.

lukan

7 months ago

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.

nilamo

7 months ago

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.

hombre_fatal

7 months ago

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.

lukan

7 months ago

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.

giantrobot

7 months ago

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.

lukan

7 months ago

That's why I wrote, "validated"

And there can also be man in the middle attacks or whatever, the efforts you do for validation depends still on your task at hand. How critical an error would be.

But even for the most trivial tasks I would never think of passing some user strings to Date and expect to get a valid value.

croes

7 months ago

Good luck with a random dependency or dependency of a dependency that doesn’t work that way.

schoen

7 months ago

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!

2muchcoffeeman

7 months ago

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.

spiffytech

7 months ago

> 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.

zelphirkalt

7 months ago

Bad news: shitty designed parts are here to stay, because people will cry for backwards compatibility.

pavel_lishin

7 months ago

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!

notatoad

7 months ago

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.

wewtyflakes

7 months ago

Those are both big qualifiers... 1. Know not to use the constructor. 2. Make assumptions about user input.

Neither seem awesome.

samwho

7 months ago

Hopefully this quiz helps with the first point :)

2muchcoffeeman

7 months ago

I don’t think this is a very good defence.

Let’s say you started a date lib right now that would take random strings and do its best.

Suppose you identify the string is only integers. What logic needs to be applied to make the example I pointed out make any sort of common sense?

notatoad

7 months ago

>Let’s say you started a date lib right now that would take random strings and do its best.

why would you do that? that's a bad idea, and no matter what implementation you choose you will end up with some silly compromises like javascript has in it's date constructor. javascript's default choices are probably no better or worse than whatever choices you would make.

if you're writing a date parser, the first thing you should do is come up with a better definition than "take random strings and do your best" unless you're putting an LLM behind it.

bevr1337

7 months ago

> you just need to never rely on the constructor for parsing user input.

A rather large disadvantage in a programming language for developing user interfaces

user

7 months ago

[deleted]

stevage

7 months ago

I can sympathise with the urge to write code that produces a valid answer if at all possible.

Usually I can overcome that urge. It's curious that these designers could not.

malux85

7 months ago

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.

norskeld

7 months ago

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...).

actinium226

7 months ago

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...

norskeld

7 months ago

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...

leipert

7 months ago

10/28. Not bad. But probably also is implementation dependent: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...

mcv

7 months ago

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.

corey_moncure

7 months ago

Javascript put me off a career in IT for 20 years, and even today I still avoid it like radioactive waste.

samwho

7 months ago

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.

zinekeller

7 months ago

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!

mnahkies

7 months ago

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...

JdeBP

7 months ago

A quick test of Vivaldi with some of those shows it nowhere near as strict as your Firefox is. Amusingly

    new Date("2025-07-12 12:30:45 BST")
is an invalid date, whereas all three of

    new Date("2025-07-12 12:30:45 GMT")
    new Date("2025-07-12 12:30:45 UTC")
    new Date("2025-07-12 12:30:45 Z")
are valid but in British Summer Time.

samwho

7 months ago

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!

saghm

7 months ago

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

samwho

7 months ago

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.

saghm

7 months ago

I think it was more than fair! The point to me of the quiz is how unexpected the behavior is in all of these cases, and the behavior being time-zone dependent is certainly part of that

the__alchemist

7 months ago

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.

NoInkling

7 months ago

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.

agos

7 months ago

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?

saghm

7 months ago

I scored what I have to assume is November 28, 2000.

samwho

7 months ago

I got a good laugh out of this.

torlok

7 months ago

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.

1oooqooq

7 months ago

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

jameshart

7 months ago

And now you have two problems

bsmth

7 months ago

Post by the author Sam Rose about it: https://bsky.app/profile/samwho.dev/post/3ltpdkr3bmk2o

samwho

7 months ago

It me.

netsharc

7 months ago

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.

samwho

7 months ago

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.

bsmth

7 months ago

Oh hi! Thanks for the great quiz

samwho

7 months ago

You’re welcome!

ctxc

7 months ago

Good job Sam! Been a while since we spoke on Twitter, but good to see you here :)

samwho

7 months ago

Dangit I’m not recognising your username, sorry!

ctxc

7 months ago

Haha, @dvsj_in :D

samwho

7 months ago

Ohhh! Thanks again for your feedback on my posts <3

hidroto

7 months ago

4 / 28 "You would have scored higher by guessing at random."

I think my strategy for JavaScript going forward is to 'drop & run'.

rkrisztian

7 months ago

If you guess at random, that's 25% probability to get the right answers, which gets you 7/28 points in average. I got 14/28 by trying hard and I still hate the result, but it's also true that the questions were largely impractical: noone parses dates like this in a real production app. We always validate the date format first. So noone should feel bad at their results.

plqbfbv

7 months ago

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.

KaiMagnus

7 months ago

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!

wiseowise

7 months ago

Cute. But things like these have tendency to be abused by “haha, js” crowd even if those things are irrelevant in practice.

rplnt

7 months ago

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.

samwho

7 months ago

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.

const_cast

7 months ago

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.

AndroTux

7 months ago

date.getYear() => 125

If that’s not relevant, I don’t know what is.

wiseowise

7 months ago

> 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...

jameshart

7 months ago

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’.

hombre_fatal

7 months ago

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.

const_cast

7 months ago

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.

jameshart

7 months ago

JS has caught up - it has a sophisticated compilation and linting ecosystem called ‘TypeScript’.

Which at least will tell you you’re using a deprecated API, but won’t overcome the dumb API naming choices JavaScript blindly imported from Java

const_cast

7 months ago

We've come full circle. The build systems for JS, a scripting language, make C++ compilation look trivial. And, unfortunately, that's reflected in the compile times.

porridgeraisin

7 months ago

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.

jameshart

7 months ago

Yes, a language that was created in 1995 was entirely justified in adopting a convention that would break within five years.

porridgeraisin

7 months ago

Java 1.0 (also released in '95) had the same behaviour. Java itself borrowed it from `struct tm` in libc, which has the same behaviour from back then up until today. It was standard back then. Whether we like it or not (I don't) doesn't change that fact. And like I said, nothing is more important than backwards compatibility.

It is just programmer education to know to add 1900 to years when using struct tm and also to use getFullYear() in JS.

wewtyflakes

7 months ago

Why is nothing more important than backwards compatibility between disparate languages written in different contexts for different contexts?

porridgeraisin

7 months ago

That javascript chose to offset from 1900 was simply because every system back then used to, including Java.

Once that had been done, future versions of javascript had to maintain the same behaviour. This is where I'm using the backwards compatibility argument.

wewtyflakes

7 months ago

Seems like JS could have called it `getYearOffset1900`, or `getYearOffet`, etc, rather than `getYear`.

porridgeraisin

7 months ago

Agreed. What I've read is that they basically duplicated the Java API, which had getYear()

I suppose the offset method was really quite entrenched so no one thought to special case that function, instead special casing the "2025" returning getFullYear()

sankalpmukim

7 months ago

9/28 - This was very good fun. Can't believe so much of the world's (important?) software is written in this toy language.

vander_elst

7 months ago

One thing I wonder is how could this have happened. It seems that this what a herd of absolute beginners would come up with: strong inconsistency and a bunch of heuristic that are not composable. But I imagine this was not the result of a bunch of beginners, what were the forces that lead to such a situation?

stevage

7 months ago

To be somewhat fair, most of what this is poking fun at is the parsing of strings that do not remotely resemble actual dates. It's very edge case behaviour. Yes, it'd be nice if the edge cases did something more predictable, like all just fail with an error, but unless you're doing something silly like passing whatever a user writes straight into Date.parse() it isn't going to matter.

Realistically, you're going to use an actual date library, because even the good bits of Date are pretty bad.

vander_elst

7 months ago

> parsing of strings that do not remotely resemble actual dates.

But this is somehow my point, what were the reasons that lead to parse those strings as dates. I guess the answer is usually legacy, but in that "legacy" why did someone need to take those decisions? My naive way of parsing dates would be to reject everything that doesn't have a well defined format while the format is well defined and at least somehow composable, but here someone had the need (I hope the had the need) to parse these seemingly random strings, I wonder why.

xmprt

7 months ago

When a language allows operator overriding or doesn't have static typing, you can end up with situations like this where a single method does 10 different things for 10 different use-cases. Even Java and C++ aren't a stranger to APIs like this (although not nearly as bad).

petee

7 months ago

I found that too painful to get further than #14

bapak

7 months ago

I gave up on like 5 and I'm a JS developer. Who dreamed this API up?

efilife

7 months ago

may I ask how long are you programming in JS for?

bapak

7 months ago

More than half of JS's own lifetime. I have great distaste for bad APIs and I'll go out of my way to not use them directly.

tlogan

7 months ago

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.

netsharc

7 months ago

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.

samwho

7 months ago

This should be fixed. Sorry about that.

dotnetcarpenter

7 months ago

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?

jzig

7 months ago

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.

cyphar

7 months ago

Well, because fun is an amorphous concept defined to be human-specific, your comment should say:

I am willing to (sarcastically) stake something of value on the premise that you are considered to be an interesting individual to interact with by your interlocutors and bystanders 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.

user

7 months ago

[deleted]

Alifatisk

7 months ago

So what’s the consensus on the solution to this chaos? MomentJs? LuxonsJs? Temporal?

efilife

7 months ago

This is really not a big deal. You never do this stuff in production before validating the input. Garbage in, garbage out

agos

7 months ago

if I were starting a new project today I would go with a Temporal polyfill

LoganDark

7 months ago

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.

bagol

7 months ago

I'm curious how would a formal spec define those behaviors.

kevincox

7 months ago

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).

the__alchemist

7 months ago

It's one of the [incorrect] answers to these questions: "Throws an error".

omoikane

7 months ago

What I have learned is that "new Date(...)" never throws errors, and you would have to do something like "new Date(...).toISOString()".

BrandoElFollito

7 months ago

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.

ivanjermakov

7 months ago

Lots of lessons in language design here. No explicit error return type and null bottom type create high ambiguity in such edge cases.

superjan

7 months ago

And don’t forget that Date objects are mutable!

GloomyBoots

7 months ago

Any explanation for ignoring parenthetical text? Is this maybe indirectly inherited from RFC 822?

elendee

7 months ago

personal take: store dates as bigints. rendering them is just a user interface issue. no need for Date parsing except to play nicely with legacy codebases. Milliseconds are your friend

a3w

7 months ago

My firefox JS console has different answers to this quiz.

jenscow

7 months ago

28 reasons to not use the built-in Date class

ilovethe80s

7 months ago

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!!!

actinium226

7 months ago

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.

mcv

7 months ago

Too many standards? Time to add another one. This one will be final, I promise.

genman

7 months ago

JavaScript is hilarious through and through.

croes

7 months ago

Why?

samwho

7 months ago

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. :)

croes

7 months ago

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?

nebrelbug

7 months ago

I got 11/28, feeling pretty proud of myself honestly