Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is January month 0 in Java Calendar?

Tags:

java

calendar

In java.util.Calendar, January is defined as month 0, not month 1. Is there any specific reason to that ?

I have seen many people getting confused about that...

like image 234
Stéphane Bonniez Avatar asked Dec 05 '08 16:12

Stéphane Bonniez


People also ask

What is Calendar month in Java?

Calendar class in Java is an abstract class that provides methods for converting date between a specific instant in time and a set of calendar fields such as MONTH, YEAR, HOUR, etc. It inherits Object class and implements the Comparable, Serializable, Cloneable interfaces.

How do you get the first day of the month for the given date in Java?

format(currentMonth); Date firstDateOfMonth = new SimpleDateFormat("yyyyMM").

What is the use of Calendar getInstance () in Java?

Calendar 's getInstance method returns a Calendar object whose calendar fields have been initialized with the current date and time: Calendar rightNow = Calendar.


2 Answers

It's just part of the horrendous mess which is the Java date/time API. Listing what's wrong with it would take a very long time (and I'm sure I don't know half of the problems). Admittedly working with dates and times is tricky, but aaargh anyway.

Do yourself a favour and use Joda Time instead, or possibly JSR-310.

EDIT: As for the reasons why - as noted in other answers, it could well be due to old C APIs, or just a general feeling of starting everything from 0... except that days start with 1, of course. I doubt whether anyone outside the original implementation team could really state reasons - but again, I'd urge readers not to worry so much about why bad decisions were taken, as to look at the whole gamut of nastiness in java.util.Calendar and find something better.

One point which is in favour of using 0-based indexes is that it makes things like "arrays of names" easier:

// I "know" there are 12 months String[] monthNames = new String[12]; // and populate... String name = monthNames[calendar.get(Calendar.MONTH)]; 

Of course, this fails as soon as you get a calendar with 13 months... but at least the size specified is the number of months you expect.

This isn't a good reason, but it's a reason...

EDIT: As a comment sort of requests some ideas about what I think is wrong with Date/Calendar:

  • Surprising bases (1900 as the year base in Date, admittedly for deprecated constructors; 0 as the month base in both)
  • Mutability - using immutable types makes it much simpler to work with what are really effectively values
  • An insufficient set of types: it's nice to have Date and Calendar as different things, but the separation of "local" vs "zoned" values is missing, as is date/time vs date vs time
  • An API which leads to ugly code with magic constants, instead of clearly named methods
  • An API which is very hard to reason about - all the business about when things are recomputed etc
  • The use of parameterless constructors to default to "now", which leads to hard-to-test code
  • The Date.toString() implementation which always uses the system local time zone (that's confused many Stack Overflow users before now)
like image 99
Jon Skeet Avatar answered Oct 26 '22 00:10

Jon Skeet


Because doing math with months is much easier.

1 month after December is January, but to figure this out normally you would have to take the month number and do math

12 + 1 = 13 // What month is 13? 

I know! I can fix this quickly by using a modulus of 12.

(12 + 1) % 12 = 1 

This works just fine for 11 months until November...

(11 + 1) % 12 = 0 // What month is 0? 

You can make all of this work again by subtracting 1 before you add the month, then do your modulus and finally add 1 back again... aka work around an underlying problem.

((11 - 1 + 1) % 12) + 1 = 12 // Lots of magical numbers! 

Now let's think about the problem with months 0 - 11.

(0 + 1) % 12 = 1 // February (1 + 1) % 12 = 2 // March (2 + 1) % 12 = 3 // April (3 + 1) % 12 = 4 // May (4 + 1) % 12 = 5 // June (5 + 1) % 12 = 6 // July (6 + 1) % 12 = 7 // August (7 + 1) % 12 = 8 // September (8 + 1) % 12 = 9 // October (9 + 1) % 12 = 10 // November (10 + 1) % 12 = 11 // December (11 + 1) % 12 = 0 // January 

All of the months work the same and a work around isn't necessary.

like image 40
arucker Avatar answered Oct 26 '22 01:10

arucker