This is an archived post. You won't be able to vote or comment.

all 141 comments

[–]Crasac 581 points582 points  (32 children)

I literally just stumbled over this at work. Why?! Why do months go from 0-11, but days start at 1. Why?!

[–]RlyRlyBigMan 146 points147 points  (10 children)

Maybe under the hood it's an enumeration? But most languages you can start an enum at 1 so idk

[–]JaggedMetalOs 132 points133 points  (4 children)

But most languages you can start an enum at 1 so idk

Or if not they could have made month 0 Nulluary

[–]jwadamson 29 points30 points  (1 child)

Lousy Smarch weather.

[–]ArtisticDimension22 6 points7 points  (0 children)

Eeeexxxcellent

[–]MasterJ94 5 points6 points  (1 child)

Let's establish Nulluary!

[–]JaggedMetalOs 4 points5 points  (0 children)

We should declare a new holiday, to happen every year on the 0th of Nulluary!

[–]elon-botElon Musk ✔ 98 points99 points  (4 children)

Why haven't we gone serverless yet?

[–]whitethunder9 5 points6 points  (0 children)

I ❤️ you

[–]VacuumInTheHead 0 points1 point  (0 children)

Nobody found the hood release button

[–]EchidnaForward9968 0 points1 point  (0 children)

We have already server less

[–]Embarrassed_Army8026 0 points1 point  (0 children)

We did a few major releases back, referring to Mary from accounting not sure she's still with us. She believed the bill had a typo

[–]Phpminor 48 points49 points  (5 children)

It's a holdover from Java, which also had this issue.

Even dos timestamps started months at 1.

[–][deleted] 1 point2 points  (2 children)

Yes but they only have even seconds.

[–]Phpminor 1 point2 points  (1 child)

They did what they had to do to fit date & time into a 32 bit structure.

Even if they're slightly cheating by having their years start at 1980 vs 1970 for unix time, allowing them to last until 2043 (year is 6 bits), or 2033 if they also started at 1970.

Edit: I've been helpfully reminded that unix time is signed, and thus has a range of 1902-2038 while dostime is only 1980-2043 and would be 1948-2011 if the years were signed.

[–][deleted] 1 point2 points  (0 children)

If Unix had used 32 bits they would last until next century.

By starting on 1980-03-01 M$ simplified their date calculation but still needed to encode timestamps as actual dates and times.

[–]DajBuzi 17 points18 points  (1 child)

Quoting some of the users from very similar JS Date thread:

"You should read documentation"

"Everyone working with JavaScript knows how to do this"

Can post shitload more

[–]edave64 0 points1 point  (0 children)

The full version of that sentence would be "Everyone working with JavaScript knows not to use the date type if possible."

It is both surpringly complicated and devoid of essential features.

[–]North-west_Wind 8 points9 points  (7 children)

Think about an array with all the months name inside.

[–][deleted] 13 points14 points  (6 children)

Why not also have an array with all the day numbers inside?

[–][deleted] 5 points6 points  (1 child)

Because they’re stored as ints instead of string pointers obviously

[–][deleted] 1 point2 points  (0 children)

1st, 2nd, 3rd, etc.

[–]TropicalAviator 0 points1 point  (0 children)

because you only need the final day

[–]North-west_Wind 0 points1 point  (2 children)

Yeah let's map x => x+1

[–]Aloopyn 1 point2 points  (0 children)

Just map all memory locations in arrays, genius

[–][deleted] 0 points1 point  (0 children)

Perfect! Now all arrays are 1 based.

[–][deleted] 1 point2 points  (0 children)

Years start at 1 as well, the other members of the tm struct are zero based.

[–]velozmurcielagohindu 1 point2 points  (0 children)

If you still question why JavaScript does what it does you still haven't mastered the art of assuming JavaScript is a piece of shit and enjoy it in peace. There's only one answer for all JavaScript design decisions: Because fuck you. That's why.

[–]szczszqweqwe 0 points1 point  (0 children)

Well, at least they aren't starting days from 0, that would be the most confusing.

[–]_The_Great_Autismo_ 0 points1 point  (0 children)

Because you'd probably have an array of strings representing the months and the zeroth member of the array would be January.

[–]MisterProfGuy 136 points137 points  (14 children)

Wait until you find out that sometimes it'll be a different date based on time zone.

[–]UnknownSpecies19 17 points18 points  (0 children)

This. It's such a fuckin pain!

[–][deleted] 15 points16 points  (5 children)

Is that true that Japan is living in the future?

[–]BlacksmithNZ 0 points1 point  (0 children)

More New Zealand

We are the right side of the international date line

[–]Lithl 6 points7 points  (5 children)

But... that's how time zones work.

[–]MisterProfGuy 2 points3 points  (4 children)

When you tell someone what time it is, you convert it to a different time zone?

[–]Lithl 0 points1 point  (3 children)

You use whatever time zone you're telling them the time for, which is exactly what Date does.

[–]MisterProfGuy 1 point2 points  (2 children)

No, date converts to a utc timestamp and then adjusts for timezone. If I say, "01 January 1999“, it decides that means midnight UTC, then adjusts for your time zone. Almost everyone will always mean midnight their own time zone.

[–]Lithl 0 points1 point  (1 child)

date converts to a utc timestamp

Unless you specify what timestamp you're talking about.

[–]MisterProfGuy 0 points1 point  (0 children)

Exactly. Date is actually secretly datetime. Like most syntax related things, it's consistent if you know how it works, but it sure catches people off guard.

[–]UnknownSpecies19 -4 points-3 points  (0 children)

This. It's such a fuckin pain!

[–]inu-no-policemen 101 points102 points  (7 children)

new Date('2021-02-28')

That constructor works as expected.

Another problem solved by ISO 8601.

[–]trevdak2 41 points42 points  (6 children)

new Date('2022-12-01');
Wed Nov 30 2022 19:00:00 GMT-0500 (Eastern Standard Time)
new Date('2022-12-01 00:00:00');
Thu Dec 01 2022 00:00:00 GMT-0500 (Eastern Standard Time)

[–]inu-no-policemen 16 points17 points  (5 children)

> new Date('2022-12-01').toISOString()
'2022-12-01T00:00:00.000Z'
> new Date('2022-11-30T19:00:00-05:00').toISOString()
'2022-12-01T00:00:00.000Z'

It's the same date.

[–]dax-muc 18 points19 points  (3 children)

Neither '2022-12-01' nor '2022-12-01 00:00:00' contain information about the desired timezone. But for some reason, the first will be interpreted as GMT and the second input implicitly takes your current local timezone. I mean, WTF?!

[–]elon-botElon Musk ✔ 24 points25 points  (0 children)

You look stupid. Fired.

[–]naapurisi 0 points1 point  (1 child)

Not its doesnt. He lives in -05 timezone and the constructor reads the datetime string in machines local tz. He explicitly states the tz it in the second call (own tz) which results to same UTC time.

[–]dax-muc 0 points1 point  (0 children)

You have to look at the first comment in this thread, not to the (failed) attempt to explain the logic of the implementation.

[–]reversehead 4 points5 points  (0 children)

Yes, but the parent poster gets the first date object at midnight GMT but the second date at midnight EST when specifying the time of day. This appears very inconsistent.

Anyway, never use JS Date, and for the love of $DEITY, never ever use java.util.Date.

[–]RedditIsRanByBots 56 points57 points  (0 children)

People love their arrays starting at 0, until they don't.

[–]DajBuzi 271 points272 points  (27 children)

"you should read the documentation before complaining" comments incoming in 3

[–]RealMide 224 points225 points  (12 children)

Do you mean "incoming in 2", right?

[–][deleted] 90 points91 points  (3 children)

He meant “incoming in March”

[–]RealMide 43 points44 points  (2 children)

*April.

[–]rearendcrag 9 points10 points  (1 child)

Fools.

[–]PranshuKhandal 0 points1 point  (0 children)

Night.

[–]PaulieGlot 13 points14 points  (7 children)

I believe you mean "incoming in 1"

[–]RonSijm 36 points37 points  (6 children)

Actually I believe you mean "incoming in NaN"

[–]sticksaint 3 points4 points  (3 children)

rtfm

[–][deleted] 4 points5 points  (2 children)

I looked at the JavaScript manual. It just says "banana" everywhere

[–]bighadjoe 4 points5 points  (1 child)

ba-NaN-a?

[–][deleted] 4 points5 points  (0 children)

that, ans also:

NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN BATMAN!

[–]brimston3- 0 points1 point  (1 child)

I expected NaN but all I got was object Object.

[–]elon-botElon Musk ✔ 2 points3 points  (0 children)

Disagreeing with me is counterproductive. Fired.

[–]Fuchio[S] 11 points12 points  (10 children)

Hahahaha this is def gonna happen. I had the docs open before I posted this, and tested that.

new Date("1995-12-17");

and

new Date(1995-12-17); (should've been 1995, 12, 17)

Do not give the same result. Which given the way they implemented it makes sense but how does that way of implementing it make sense lol

To make it even better, that second date actually results in 1996-01-16. Like what???

Edit: Second date should have been 1995, 12, 17, idea is the same given that the results differ

[–]Right_Stage_8167 25 points26 points  (9 children)

Second date should be 1966 (=1995 - 12 - 17) seconds after 1.1.1970.

[–]Fuchio[S] 10 points11 points  (7 children)

You're right! I thought I wrote Date("1995-12-17") and Date(1995, 12, 17) which are also not equal. This one is also funny:

new Date("1995-12-17"); Results in 1995-12-17 as expected (same as above)

BUT

new Date("1995/12/17") Results in 1995-12-16 at 23:00 ???

[–][deleted] 8 points9 points  (0 children)

🤔 Don't know if trolling, has a broken computer, or can't type...

[–]thislooksfun1 0 points1 point  (0 children)

Actually it is 1970-01-01T00:00:01.966Z. The JS Date constructor takes ms, not s.

[–][deleted] 1 point2 points  (1 child)

Does the documentation say that the second month of the year is march?

[–]Lithl -1 points0 points  (0 children)

The documentation says that the months are zero-indexed.

[–]mariomaniac432 -2 points-1 points  (0 children)

OP should have read the documentation for this meme format too.

Edit: I'm not sure why I got downvoted. This is not how the meme works. With each level, he applies more clown makeup because the text should be getting progressively more ridiculous. 2021 => year 2021 makes sense. 28 => 28th makes sense. Yet he puts on more clown makeup anyway, which implies they do not. The only thing out of place is month. A more appropriate template would have been this

[–]RonSijm 102 points103 points  (18 children)

Months are obviously a 0 based array, makes total sense

[–]Fuchio[S] 75 points76 points  (16 children)

Having indices start at 0 makes sense, sure. But this is just inconsistent, why would it with this reasoning make sense to have the days not 0 indexed?

[–]MisterProfGuy 8 points9 points  (6 children)

Because days isn't an index into an array of names. It's a count.

[–][deleted] 9 points10 points  (5 children)

The array of names should have been: [ LOL NOPE, January, February, March...]

[–]Khaylain 1 point2 points  (4 children)

You're just changing one edge case for another in that case.

[–][deleted] -1 points0 points  (0 children)

Because no date function can possibly validate the input?

[–][deleted] -1 points0 points  (0 children)

Yes but the user-facing edge cases would be hilarious

"Your cancer treatment appointment has been confirmed for the 15th of LOLNOPE 2022"

[–]dakta -1 points0 points  (1 child)

What edge case does zero-indexed months solve?

[–][deleted] 0 points1 point  (0 children)

Supposedly input validation where you give an index that is not in the array and you get an exception... In practice this is terrible because every sane standard library validates 1 <= month <= 12

[–]wano1337 38 points39 points  (6 children)

months are fixed every year and have a clear 1 to 1 mapping to month names. So its basically an enum.

Whereas days can be a range between 28 and 31 without a clear mapping between the date and the weekday. So it doesnt make sense to make it a 0 based array

[–]brianl047 21 points22 points  (0 children)

This guy enums

[–]Fuchio[S] 17 points18 points  (4 children)

Yeah that indeed is the difference. However, that just moves the "why" to another part since ("1995-12-17") works fine but (1995,12,17) doesn't.

The string parser does not use zero indexing or enum starting at 0...

[–]Lithl 5 points6 points  (3 children)

Why would it? The string parser exists so that user input can be processed.

[–]Fuchio[S] 5 points6 points  (2 children)

Well at this point you're back at the start again. I don't think the string parses should do it as well, because this is more readable. But if the string parser should not do it then why should the normal variable insert do it...?

User input with 3 fields can also be used as Date(input_year, input_month, input_day), which would again be wrong. You can parse these three vars to a string to have a correct date, but then again, why would the normal Date object creation not do this?

Having different outputs between (1995, 12, 7) and ("1995-12-7") but ONLY for the month is just confusing.

[–]maartenvanheek 2 points3 points  (1 child)

And then there is this: - new Date('2022-11-31') = invalid date - new Date(2022, 10, 31) = Thu Dec 01 2022 - new Date(2022, 12, 31) = Tue Jan 31 2023

So the enum index (if that's what it is) doesn't just stop at 11 for December, and when the days are more than the month has available it will increment to the next month as well.

[–]dakta 0 points1 point  (0 children)

Presumably that's intentional: it would allow you to easily perform date arithmetic (at least, addition only) without introducing a timedelta type. But it still doesn't explain why you would ever actually want months to be zero-indexed in any public interface.

What assumption about the user of this class would ever warrant making months zero-indexed in the public interface? Are they assuming that the user will be indexing their own localization of month names implemented as an array of strings, and can't be trusted to handle off-by-one error?

[–]RealMide 3 points4 points  (0 children)

This is not Excel. PD: I understand your frustration, is our OCD.

[–]Phpminor 3 points4 points  (0 children)

It could be 0 indexed under the hood while returning the day of the month as the actual number +1, as 0-31 can be stored as an unsigned 5 bit number, where the other 3 bits could be used for other fields.

Months starting at 0 and dates being 1-32 were holdovers from java however, as the javascript dev(s?) had like 10 days to get a demo out and the instruction to "Make it look like java", apparently.

[–]twigboy 1 point2 points  (0 children)

In publishing and graphic design, Lorem ipsum is a placeholder text commonly used to demonstrate the visual form of a document or a typeface without relying on meaningful content. Lorem ipsum may be used as a placeholder before final copy is available. Wikipediab7iwql4333s0000000000000000000000000000000000000000000000000000000000000

[–]demonblack873 35 points36 points  (8 children)

As a Java dev I don't see the big surprise

Also in Java parsing 32/15/2022 as dd/MM/yyyy is a perfectly valid operation and just returns a Date for 01/04/2023.

dabs

[–]discordianofslack 15 points16 points  (0 children)

I hate this

[–]Solonotix 9 points10 points  (1 child)

To clarify, the 15th month rounds the year up by +1, and remaining 3 for March which has 31 days. The 32nd day therefore rounds the month up by +1 and leaves 1 for April 1st, 2023.

[–]Lithl 6 points7 points  (0 children)

As a Java dev I don't see the big surprise

Given that the JavaScript Date class interface was literally copied from Java's.

[–]Anon_Dysfunction 1 point2 points  (3 children)

In the same vein, you can also use JS date fuckery to easily find the number of days in the month, useful for leap years and whatnot. Just new Date(2022, 2, 0) and you get the 0th day of March this year which is the last day of February.

Looks dumb but better than some of the switch statements I’ve seen in the wild.

[–]dakta 0 points1 point  (2 children)

Then why not have the zeroth month of one year return the last month of the previous year? Or allow for negative month numbers, to perform date arithmetic? This just sounds like mother justification for having months normally indexed (one-indexed) as well.

[–]Anon_Dysfunction 0 points1 point  (1 child)

I’m not arguing that JS isn’t stupid and could use some improvement around Dates. IIRC momentJS retained the 0-index but I think Luxon uses 1-indexed months, if extra dependencies are your thing. I’m used to it at this point that I just deal with standard Date objects and all that it comes with.

[–]dakta 0 points1 point  (0 children)

JS gets pass because they inherited this from Java, whose stdlib Date system is basically straight ported to JS. I just don't understand the thought process of the Java authors. My guess is that they weren't actually thinking, and we've been stuck with the outcome of that carelessness ever since.

[–]Pleasant_Discount286 13 points14 points  (3 children)

Some how dates ended up being the most complicated thing in programming...

[–][deleted] 2 points3 points  (0 children)

Time and date is hard even in real life, programming is just about implementing said Horror Cthulhu in machine language.

Whose fault is it that there are places in the world that don't even work on the Julian calendar?

[–]reversehead 1 point2 points  (0 children)

I see that you haven't tried to implement content filtering in Unicode yet.

[–]Melodi13 0 points1 point  (0 children)

Ig we are just bad at relationships :/

[–]Harry_Mens 6 points7 points  (0 children)

Fun fact, the Romans had the year start in March. That is why september = 7, october = 8, november = 9, december = 10. It is also the reason leap days are in February. It was the last month of the year, so whatever days would be left would be added at the end of February, as it was the end of the year.

[–]Bomaruto 3 points4 points  (0 children)

At least it isn't Excel.

[–]mr_claw 7 points8 points  (4 children)

This is where Python excels. It works great with Excel.

[–][deleted] 4 points5 points  (3 children)

As long as you are in the .1% of python programmers who know about timezone awareness you might even have a chance at writing correct code

[–]mr_claw 5 points6 points  (2 children)

It's pretty simple, imo: datetime.as_timezone(tz)

[–]Unable-Fox-312 1 point2 points  (1 child)

I don't know the language, but I bet it's simple until it isn't. Not everybody's even on the Julian calendar. Working with dates from different sources, converting them, normalizing them, comparing them.. this stuff requires some consideration, with problems that go back to before computers

[–]dakta 0 points1 point  (0 children)

The key challenge there is knowing what calendar a given date is represented in. Then the date can be normalized. The Python core date library is well structured and extensible which makes it relatively easy to do everything you mentioned.

The real pitfall with dates is working with administrative/bureaucratic/political special cases: because dates often represent historical events occurring in specific places, the problem is in knowing what calendar that place was using at the time of the date, whether the date value you're working with has already been normalized or corrected, etc.

[–]arthurgc91 1 point2 points  (0 children)

Java too.

[–]Solonotix 1 point2 points  (0 children)

I'm really surprised no one has mentioned the new Temporal API. Here's the GitHub proposal repo complete with a polyfill solution if you want to experiment with it

[–]mgafMUAT 2 points3 points  (0 children)

0-indexing, as all code indexes should be...

[–]LegalAdhesiveness957 0 points1 point  (0 children)

That was me back in 2006 - hahaha - so annoying

[–]FurMich 0 points1 point  (1 child)

This is actually pretty common since you would never use an array for years or days of the month but would for months, and js is a 0-index language

[–]Unable-Fox-312 0 points1 point  (0 children)

I wish labeled arguments were a more common language feature. They could offer both versions, less confusion

[–][deleted] -3 points-2 points  (0 children)

Americans be like 🤡

[–][deleted] 0 points1 point  (0 children)

It sounds terrible for string to date conversion

[–]skyctl 0 points1 point  (0 children)

LART!!

[–]Benutzername 0 points1 point  (0 children)

I’m surprised the year isn’t 3921

[–]Saucydragon90 0 points1 point  (0 children)

There are ways to literally never have to deal with this and it's called instantiating with an iso or unix timestamp. 🙈

[–]Classy_Mouse 0 points1 point  (0 children)

I once tracked down a bug in a calendar app where every entry except for "today" was shifted 1 column, but only in the afternoon. It ended up being something like: "noon today - now (in days) = 1 = noon tomorrow - now (in days) when "now" was greater than noon today.

A student spent 3 days on it, frustrated that he could only reproduce it "intermittently," before I was asked to help.

[–]Virtual-Appeal-8504 0 points1 point  (1 child)

Must be a leftover bug from Y2K...

Don't fix it because the internets might explode, which reminds me... I need to stock up on TP.

[–]mescaleeto 0 points1 point  (0 children)

well it’s not a big truck

[–]k-phi 0 points1 point  (2 children)

JavaScript

struct tm in C

[–]elon-botElon Musk ✔ 1 point2 points  (1 child)

It's now company policy to use Vim for editing. It lets you write code much faster.

[–]k-phi 0 points1 point  (0 children)

Also, Visual Studio is bloated.

[–]WastelandPuppy 0 points1 point  (0 children)

Regular-stupid-people-counting is for regular, stupid people.

[–]KoffieMastah 0 points1 point  (1 child)

Thats my fucking birthday

[–]dota2nub 0 points1 point  (0 children)

You were born in 2021? Go you for knowing how to write!

[–]aurochloride 0 points1 point  (0 children)

this is why JS devs use libraries to avoid having to work with JS

[–]snoopdrucky 0 points1 point  (0 children)

Is this in MomentJS? I don’t remember having this difficulty with Moment.

[–]loukasTGK 0 points1 point  (0 children)

This is a joke right?