Java Gregorian Calendar返回错误的月份

时间:2013-12-04 05:24:15

标签: java calendar gregorian-calendar

所以我现在已经在这几个小时了,它会返回正确的年份和日期,但由于一些奇怪的原因,它会返回错误的月份。我确定这是一个简单的修复,但我似乎无法弄明白。

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

3 个答案:

答案 0 :(得分:3)

TL;博士

要获得当月的1-12号数字:

LocalDate.now()
         .getMonthValue()

最好指定您想要的/预期的时区。

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

同样致电.getYear().getDayOfMonth()

详细

  

它返回错误的月份

正如其他人所说,在Calendar,1月至12月的月份疯狂地编号为0-11 而不是1-12。旧日期时间类中许多糟糕的设计决策之一。这些类现在已经遗留下来,取而代之的是java.time类。

  

那么有解决方法吗?

是的,有一种解决方法。使用一个好的日期时间库而不是java.util.Date/Calendar的混乱。现代的方法是使用java.time类。

当前时刻

时区对于获取当前日期和时间至关重要。对于任何给定时刻,日期和挂钟时间因区域而异。

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

您可以通过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() );
  

当前时间:2016-12-14T04:54:44.802-05:00 [美国/蒙特利尔]

     

年是2016年

     

月份是12

     

月份名称为décembre

     

日是14

请参阅live code in IdeOne.com

如果您只关心日期而不关心时间,请使用LocalDate课程。

LocalDate.now( z );

特定时刻

您可以将时刻指定为自UTC 1970年第一时刻的epoch以来的毫秒数。

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

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

该输出中的ZZulu的缩写,表示UTC

您可以指定时区以适应特定的挂钟时间。

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

zdt.toString():2009-02-13T18:31:38.765-05:00 [美国/蒙特利尔]

请参阅live code in IdeOne.com

建议以这种方式交换日期时间数据。最好以ISO 8601格式序列化为文本。例如:2009-02-13T23:31:38.765Z


关于java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和& SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore


旧答案 - Joda-Time

更新:现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

示例代码

今天

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

跑步时......

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

某一天

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

跑步时......

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。当我注意到你的任意选择Long导致星期五第十三次时,我只是感到寒冷!

答案 1 :(得分:3)

出于某些疯狂的原因,Calendar类使用月份的基于零的索引(Jan == 0,Feb == 1等),但所有其他日期部分都是基于一个(匹配其实际数字) )。

据推测,这是在一些蹩脚的枚举尝试中完成的,但这只是愚蠢的。

我的建议是永远不要使用日历。请改用Joda-Time

答案 2 :(得分:0)

尝试使用由Java 8提供的新日期和时间库,这些库受Joda-Time的启发,并且易于使用。它还解决了月份从0开始的问题。