Calendar Returns Wrong Month

Java Calendar returns wrong month

When you use DAY_OF_YEAR you set the number day of the current year.

  • https://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html#DAY_OF_YEAR

DAY_OF_YEAR Field number for get and set indicating the day number
within the current year.

This overrides all sensible configuration like month or year (to current year and month of the number day).


So instead of use DAY_OF_YEAR you may use DAY_OF_MONTH which seems is what you are looking for, this sets the day of the month you set before.

  • https://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html#DAY_OF_MONTH

DAY_OF_MONTH Field number for get and set indicating the day of the month. This is a synonym for DATE. The first day of the month has value 1.

So the configuration you are looking for definetively seems it would be like next:

Calendar cal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getTimeZone("UTC"));
cal.set(Calendar.YEAR, 2017);
cal.set(Calendar.MONTH, Calendar.JUNE);
cal.set(Calendar.DAY_OF_MONTH , 26);
cal.set(Calendar.HOUR_OF_DAY, 9);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);

Then when you call getTime you will get:

Mon Jun 26 11:00:00 CEST 2017

Calendar.MONTH gives wrong value

Keep in mind that months values start from 0, so October is actually month number 9.

http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Calendar.html#MONTH

Java Calendar returns wrong date

Your problem isn't the Date class, but passing the wrong parameter.

Change:

cstart.get(Calendar.DATE)

to

cstart.get(Calendar.DAY_OF_MONTH)

EDIT: This does not solve the issue.
There does seem to be some problem, but since the OP is using in-house developed Date/.. classes, I 'm not going to pursue this further.
For those who want more information about that, check the comments.

Java Gregorian Calendar Returns Wrong Month

tl;dr

To get a number 1-12 for current month:

LocalDate.now()
.getMonthValue()

Better to specify your desired/expected time zone.

LocalDate.now( 
ZoneId.of( "America/Montreal" )
).getMonthValue()

Similarly call .getYear() and .getDayOfMonth().

Details

it returns the wrong month

As others said, in Calendar the months January-December are crazily numbered 0-11 rather than 1-12. One of many poor design decisions in the old date-time classes. Those classes are now legacy, supplanted by the java.time classes.

So is there a work around this?

Yes, there is a workaround. Use a good date-time library rather than the mess that is java.util.Date/Calendar. The modern way is with the java.time classes.

Current moment

Time zone is crucial in getting the current date and time. For any given moment the date and wall-clock time vary by zone.

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.now( z );

You can interrogate for the various components such as year, month number, localized name of month via Month enum, and day-of-month.

System.out.println ( "Current: " + zdt );
System.out.println( "Year is " + zdt.getYear() );
System.out.println( "Month is " + zdt.getMonthValue() );
System.out.println( "Month name is " + zdt.getMonth().getDisplayName( TextStyle.FULL , Locale.CANADA_FRENCH ) ); // Or Locale.US, Locale.ITALY, etc.
System.out.println( "Day is " + zdt.getDayOfMonth() );

Current: 2016-12-14T04:54:44.802-05:00[America/Montreal]

Year is 2016

Month is 12

Month name is décembre

Day is 14

See live code in IdeOne.com.

If you only care about the date and not the time-of-day, use the LocalDate class.

LocalDate.now( z );

Specific moment

You can specify a moment as a count of milliseconds since the epoch of first moment of 1970 in UTC.

long input = 1_234_567_898_765L ;
Instant instant = Instant.ofEpochMilli( input );

instant.toString(): 2009-02-13T23:31:38.765Z

The Z in that output is short for Zulu and means UTC.

You can assign a time zone to adjust into a particular wall-clock time.

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );

zdt.toString(): 2009-02-13T18:31:38.765-05:00[America/Montreal]

See live code in IdeOne.com.

I do not recommend exchanging date-time data this way. Better to serialize to text in ISO 8601 formats. For example: 2009-02-13T23:31:38.765Z


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

Where to obtain the java.time classes?

  • Java SE 8 and SE 9 and later

    • Built-in.
    • Part of the standard Java API with a bundled implementation.
    • Java 9 adds some minor features and fixes.
  • Java SE 6 and SE 7
    • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
  • Android
    • The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
    • See How to use….

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.


Old Answer - Joda-Time

Update: The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

  • Use Joda-Time 2.3 now.
  • In the future, with Java 8, consider moving to JSR 310: Date and Time API which supplants the Date/Calendar classes and is inspired by Joda-Time.

Example Code

Today

// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// import org.joda.time.*;

// Generally best to be explicit about time zone rather than depend on default.
DateTimeZone denverTimeZone = DateTimeZone.forID( "America/Denver" );
java.util.Locale locale = Locale.FRANCE;

DateTime now = new DateTime( denverTimeZone );

System.out.println( "Current Year, Month & Day for: " + now );
System.out.println( "Year is " + now.year().getAsText( locale ) );
System.out.println( "Month is " + now.monthOfYear().getAsText( locale ) );
System.out.println( "Day is " + now.dayOfMonth().getAsText( locale ) );
System.out.println(); // blank line.

When run…

Current Year, Month & Day for: 2013-12-04T01:58:24.322-07:00
Year is 2013
Month is décembre
Day is 4

Some Day

// Not generally a good idea to focus on integers for working with date-time, but you asked for it.
DateTime someDateTime = new DateTime( 1234567898765L, DateTimeZone.UTC );

System.out.println( "Set Value of 1234567898765L is: " + someDateTime );
System.out.println( "Year is " + someDateTime.year().getAsText( locale ) );
System.out.println( "Month is " + someDateTime.monthOfYear().getAsText( locale ) );
System.out.println( "Day of month is " + someDateTime.dayOfMonth().getAsText( locale ) );
System.out.println( "Day of week is " + someDateTime.dayOfWeek().getAsText( locale ) );
System.out.println( "Day of year is " + someDateTime.dayOfYear().getAsText( locale ) );

When run…

Set Value of 1234567898765L is: 2009-02-13T23:31:38.765Z
Year is 2009
Month is février
Day of month is 13
Day of week is vendredi
Day of year is 44

P.S. I just got the chills down my back when I noticed your arbitrarily chosen Long resulted in Friday The Thirteenth!

Calendar returns wrong month and year Java

Those are all static fields from the Calendar class. Java allows static fields (and methods) to be accessed on expressions that resolve to an instance's reference value the same way it does on type names

now.ERA
// is equivalent to
Calendar.ERA

The Calendar class provides a get(int) method for getting the value of a date field.

now.get(Calendar.MONTH);

Android - GregorianCalendar displays wrong month

GregorianCalendar represents months with numbers in the range from 0 to 11. This means that the number 0 is represented as January and 11 is represented as of December.

Therefore you need to subtract 1 if your API is not using the same logic as the Java implementation.

Updated:
GregorianCalendar(2016, 1, 30) is understood as 30th of February. This is internally converted to 1st of March, therefore when you subtract one month from the date, you get 1st of February. You need to create an instance of GregorianCalendar class already with the subtracted month number, ie. January as 0, February as 1 and so on.

Calendar.get(Calendar.DAY_OF_MONTH) returning wrong day

Glad that the answer by Robby Cornelissen solved your problem. I should like to explain what happened and why that answer helped.

When you are using the three-arg GregorianCalendar constructor, it “Constructs a GregorianCalendar with the given date set in the default time zone with the default locale.” Quoting the docs; italics are mine. In your case this is GMT+3 (now; the important thing is that in August it will still be GMT plus something).

What the docs are not so clear about is that hour of day is set to 0, so you’ve really got a point in time of 10 August 2017 0:00 at zone offset +3:00. You would really have wanted the GregorianCalendar not to worry about time of day, but there’s no such thing. This is one of the reasons why I recommend LocalDate instead as I mentioned in a comment.

When you change the time zone, the point in time stays the same, but since you were ahead of GMT in your own time zone, you now have 9 August 2017 21:00 UTC. So 9 is the correct day-of-month value now.

I think the greatest surprise is that the toString method still produces DAY_OF_MONTH=10. When GregorianCalendar computes which fields is obscure to me, but obviously is still remembers the old value at this point.

For formatting you use new SimpleDateFormat("dd"). This formatter uses your default time zone of GMT+3, and the point in time from the calendar object, correctly producing 10. If you had wanted it to produce the day-of-month from the calendar, you might have set its time zone to UTC too.

dateOfBirth.get(Calendar.DAY_OF_MONTH) produces the correct value of 9.

The funny thing is that if after this call I repeat your line:

    System.out.println("Calendar substring:\t\t" 
+ dateOfBirth.toString().substring(dateOfBirth.toString().indexOf("DAY_OF_MONTH"),
dateOfBirth.toString().indexOf("DAY_OF_MONTH") + 15));

This time it produces:

Calendar substring:     DAY_OF_MONTH=9,

So that field has now been computed.

In Robby Cornelissen’s code the calendar object is born with UTC time zone, so when you set the date, it is really set to — well, 10 July 2017 this time, but 0:00 UTC. This corresponds to 3:00 in your time zone, but the date is also 10 July there, so the rest of your code will produce the 10 you expected. However, users in time zones west of Greenwich will have problems now because their SimpleDateFormat will use their time zone, which is behind GMT, so they will see a formatted date of 09.

For the sake of completeness here’s the ThreeTen (Backport) version:

    LocalDate date = LocalDate.of(2017, Month.AUGUST, 10);
System.out.println("Day of month:\t" + date.getDayOfMonth());

This prints

Day of month:   10

A LocalDate has got neither any time of day nor any time zone, leaving a lot less room for confusion. Contrary to Calendar it also numbers the months the way humans do, so 7 is July and 8 is August.



Related Topics



Leave a reply



Submit