Java Gregorian Calendar Returns Wrong Month
Asked Answered
H

3

0

So I been at this for a few hours now and it returns the correct Year, and Day but for some odd reason it returns the wrong month. I'm sure its a simple fix but I can't seem to figure it out.

package gregoriancalendar;

import java.util.GregorianCalendar;

public class Calendar8_5 {



public static void main(String[] args){

GregorianCalendar calendar = new GregorianCalendar();
System.out.println("Current Year, Month & Date: ");
System.out.println("Year is " + calendar.get(1));
System.out.println("Month is " + calendar.get(2));
System.out.println("Day is " + calendar.get(5));


calendar.setTimeInMillis(1234567898765L);
//Elapse Time
System.out.println("Set Value of 1234567898765L");
System.out.println("Year is " + calendar.get(1));
System.out.println("Month is " + calendar.get(2));
System.out.println("Day is " + calendar.get(5));
   }
  }
Hopper answered 4/12, 2013 at 5:24 Comment(8)
Have you read the javadoc?Infant
Probably because of this? #344880Aba
Alright that makes more sense so calendar is 0-11 11 being december. Common sense would tell me to add 1 but I know that won't work and give me an odd result. So is there a work around this?Hopper
Why wouldn't it work to add 1?Bagger
Adding one results in the 111 or 49Hopper
@Hopper What did you mean by //Elapse Time?Behre
Duplicate: Calendar returns wrong monthBehre
Duplicate: Creating java date object from year,month,dayBehre
B
3

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 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.

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!

Behre answered 4/12, 2013 at 9:2 Comment(2)
Basil, Thanks for the full explanation and example of Joda Time. This really helps a lot. I will be playing with this a bit and see how it works out :)Hopper
@Hopper The more you know about Joda-Time, the more you’ll like it. Joda-Time is one of the best reasons to use Java. Search StackOverflow for joda to find many examples and tips. Working with date-time is often tricky and confusing, but Joda-Time is a big help.Behre
T
3

For some insane reason, Calendar class uses a zero-based index for month (Jan==0, Feb==1, etc), but all other date parts are one-based (matching their actual numbers).

Presumably it was done in some lame attempt at an enumeration, but it's just stupid.

My advice is to never use Calendar. Use Joda-Time instead.

Thread answered 4/12, 2013 at 9:15 Comment(1)
Thank you this really helps. reading and doing some more research I see theres a bit of a preference to using Joda-Time.Hopper
A
1

Try using new date and time library provided by Java 8, which are inspired by Joda-Time and they are easy to use. It also solved problem of having month starting with 0.

Alleneallentown answered 12/8, 2016 at 1:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.