2

So Im working on an Calendar programm and to change the Months im asking for the int of the month.

If I type calendar.get(Calendar.JANUARY) i get 1 as return, which is correct because first month. But if I type calendar.get(Calendar.FEBUARY) i get 2018 in respond which of course is wrong. Does anyone know what the problem could be?

Calendar cal1 = new GregorianCalendar();
int month = cal1.get(Calendar.JANUARY);
int month2 = cal1.get(Calendar.FEBRUARY);
int year = cal1.get(Calendar.YEAR);
  • The `Calendar` and `GregorianCalendar` classes are long outdated, poorly designed, cumbersome to work with and sometimes confusing, as you have experienced. Allow me to suggest you use [`java.time`, the modern Java date and time API,](https://docs.oracle.com/javase/tutorial/datetime/) instead. – Ole V.V. May 21 '18 at 07:55

2 Answers2

1

Calendar#get gets a field value. Calendar.JANUARY is not a field number, it's a potential field value. The only static fields in Calendar that you use with get (and set) are the ones whose descriptions start with "Field number for get and set...".

To get the month, use cal1.get(Calendar.MONTH).

The Calendar API is...unfortunate, not least because it predates enums and so int was used for get/set's field identifier parameter where an enum was really needed. While get takes an int, and Calendar.JANUARY is an int, they're ints in different domains. See Ole V.V.'s answer for the modern, dramatically-improved alternative: java.time.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
1

java.time

T.J. Crowder’s answer is correct. Allow me to supply the real, good and modern solution to your problem.

    ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("Atlantic/Stanley"));
    // 2018-05-21T05:02:23.942763-03:00[Atlantic/Stanley]
    Month monthEnum = zdt.getMonth(); // MAY
    int monthNumber = zdt.getMonthValue(); // 5
    int year = zdt.getYear(); // 2018

I ran the code just now and have given results in comments after each code line. Please put your desired time zone where I have put Atlantic/Stanley since the month does not change at the same point in time in different time zones. Do you agree with me that this code is clearer and more natural and leaves less room for confusion? BTW, if you’re only interested in the date, not the time of day, use LocalDate instead of ZonedDateTime, the rest of the code will be the same.

To get the numbers of specific months:

    int januaryNumber = Month.JANUARY.getValue(); // 1
    int februaryNumber = Month.FEBRUARY.getValue(); // 2

What happened in your code?

As T.J. Crowder has already said, Calendar.get expects a field number, for example Calendar.MONTH or Calendar.YEAR. Calendar.JANUARY is 0. Zero?! It’s another confusing thing about Calendar, month numbers are 0-based, that is, they go from 0 for January through 11 for December. Anyway, 0 is also the field number of Calendar.ERA. GregorianCalendar uses 0 for BC (or more religion neutral: BCE for before common era) and 1 for AD (CE, common era). Since your date is in the common era, you get 1. Which, by the way, would have been incorrect for month of January since months are 0-based.

Similarly, Calendar.FEBRUARY equals 1 and coincides with field number Calendar.YEAR, which I why you got the year.

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • Excellent. I haven't used `java.time` (because I haven't done virtually any Java programming in the last few years) so couldn't include this in my answer. I should have at least mentioned `java.time`, though, I do know *about* it... – T.J. Crowder May 21 '18 at 08:29
  • Uhhh that is a very nice Solution. Sadly my Java-Teacher is really annoying and forces us to use GregorianCalendar. But she overall just uses really old APIs, like we are not allowed to use JavaFX even if we can use it – Sarah Sparda May 21 '18 at 09:52
  • Das finde ich Schade, @SarahSparda. Such teachers exist, it makes me wonder. Maybe she just cannot find the time to learn the new APIs herself. Speculation, though. – Ole V.V. May 21 '18 at 10:42