100

Some popular programming languages use month numbering which is off by 1 -- JavaScript comes to mind, as does Java, and if memory serves, C is another. I have some questions:

  • If you are going to be ignoring the month numbering used by laypeople, then why not for the sake of consistency also ignore the day numbering used by laypeople, and number the days in each month starting from 0 ?
  • Why is this so common?
  • Whose idea was this in the first place?
Joe Doyle
  • 6,363
  • 3
  • 42
  • 45
Robert L
  • 1,963
  • 2
  • 13
  • 11
  • Arrays, start at 0, and people refer to days by numbers? – glasnt Sep 21 '09 at 05:57
  • 13
    @TomatoSandwich: quite often people refer to _months_ by numbers, and they number them starting from _1_. – Robert L Sep 21 '09 at 06:01
  • 2
    API Programmers aren't gods by the way; sometimes mistakes get into the implementations; just deal with it. Not that this is exactly a case (you don't even say what language), but don't expect everything to be perfect. I admire wanting to know the reason though. – Noon Silk Sep 21 '09 at 06:01
  • There ya go, 280Z28, is that any better? – paxdiablo Sep 21 '09 at 06:01
  • 5
    In Japan, they only use numbers. They don't use January, February, etc. The Western world also uses numbers very often. I hope they never make another programming language that chooses array style over spoken language style again. It's such a simple fix for something that's going to be used millions of times. – Wolfpack'08 Oct 20 '11 at 10:12
  • 1
    Agreed, while not a hanging offence, whoever did this just wasted ten minutes of my time and deserves a slap with a medium-sized wet fish. – James McCormack Nov 13 '14 at 17:26
  • As an upside, month calculations are a bit easier with zero based months: https://stackoverflow.com/a/18002968/371137 . – Perseids Aug 30 '15 at 11:44
  • [`java.time.Month`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/Month.html) has sane counting, 1-12 for January-December. – Basil Bourque Sep 01 '19 at 18:24

3 Answers3

57

The use of zero to start counting is actually an optimization trick from Assembly programmers. Instead of assigning 1 to the count register, they XOR'ed the register with itself, which was slightly faster in CPU cycles. This meant that counting would start with 0 and would always be up to the length of elements, excluding the last one.

Also, the use of zero is also popular with pointer arithmetics where you would use one base pointer pointing at some allocated memory, plus a second pointer which would be at an offset from this base pointer. Here, using the value zero makes a lot of sense to point the offset to the base of the memory block. (General array logic tends to be the base address plus the offset x record size.)

And zero-based month numbers? Often, many programming environments calculate the data as a number of days since some default data. December 31, 1899 is a popular date, although there have been plenty of other dates used as base date. All other dates are offset from this base, and will just be stored as one single number. Fractions would be used to indicate hours, minutes and seconds, where 0.25 would be 24/4 = 6 hours. Thus, to transform a date into a real date, all the environment has to do is transform this number into a real date.

However, the combination of zero-based arrays and 1-based month values does bring a problem. To get the month name of month 9, you would have to get item 8 from the month array. Some developers would be happy with decreasing the month number before getting it's name. Others preferred to change the month into something zero-based since people just want to know the name, not the number. It's a personal view.

Wim ten Brink
  • 25,901
  • 20
  • 83
  • 149
  • 94
    The JavaScript and AS3 Date constructors take real values for everything "except" the month, which for an unknown reason must be specified as zero-based. That's unquestionably a terrible API design. – Triynko Dec 04 '13 at 22:14
  • 3
    I agree. This just cost me an hour trying to figure out why my date was a month out. It doesn't really make much sense for everything to be 1 based except for the month. Unfortunately, its probably unfixable, otherwise we'd end up with another Y2K problem :-). – mike gold Dec 31 '14 at 04:00
  • 2
    Tl;dr: Because of the array lookup `monthName[monthNumber]` or `mon_name[tm_mon]` with [time.h notation](http://www.cplusplus.com/reference/ctime/asctime/). – Perseids Aug 30 '15 at 11:36
  • The XOR-with-itself thing is a bit of a red herring; it's an Intel thing. Other MPUs had other ways to zero registers; some had efficient ways to set them to 1 as well. The main reason for zero-based things is index calculations; sometimes they’re useful for arithmetic too. – al45tair Mar 02 '16 at 09:19
6

It is what it is, and the huge weight of software built to that assumption means it's going to be around for a while.

My opinion is that it was the fault of C, and all those other Johnie-come-lately languages just conformed with it.

You get some funny situations from people who don't know better. One of the few Y2K bugs our team found was a web site proudly proclaiming the year was 19100 simply because they prefixed the struct tm year with the literal "19".

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
4

Yes, the Romans had problems with zero as well.

This is just a [non-intuitive] consequence of mathematics (being a strong component of programming, especially early programming) defining zero as the first (problematic term that one) real, positive* natural number, and since an array is indexed with real, natural numbers the "first" element is at index 0.

Months are really named values in an array, where days and years are numbered values - it would perhaps be more useful to think of days/years as being in arrays which look like { "1", "2", "3", ... } themselves.

As to why this is so common (apart from being mathematically correct) well all the languages you listed descend from a common origin for one thing...

Edit:

Looking further into it, this wikipedia link details several good and interesting reasons for zero indexing (which does not directly speak to why months are zero-indexed but I think that's covered already), and this SO link has answered the question before.

Looks like the prevailing opinion is either "historical accident" or "because months are not numbers so cannot be compared to day/year storage" depending on who you ask.

* Sorry, sorry, physics!=maths coming back to bite me there. Off to iron my hands now.

Community
  • 1
  • 1
annakata
  • 74,572
  • 17
  • 113
  • 180
  • 5
    Zero is not a positive number. It is also not a negative number. – Robert L Sep 21 '09 at 06:15
  • Good point, perhaps you should change it to "natural number". – paxdiablo Sep 21 '09 at 06:18
  • 1
    Interesting, I had always thought that C arrays start at 0 to simplify the pointer arithmetic: `a[0]` == `*(a + 0)`. – too much php Sep 21 '09 at 06:31
  • 2
    Actually, in computing, you can have a positive and negative zero if you use the Ones' complement system. Fortunately, that system is almost never used again. See http://en.wikipedia.org/wiki/Ones'_complement#Ones.27_complement – Wim ten Brink Sep 22 '09 at 07:40
  • Month is also a number as well, just as day in our culture. The first month in a year is really called "1(st) month", and the last is called "12(th) month" – Michael Tsang Feb 27 '19 at 08:00