简体   繁体   中英

Java Gregorian Calendar Returns Wrong Month

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));
   }
  }

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

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

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM