GregorianCalendar意外值

时间:2013-09-16 07:16:10

标签: java gregorian-calendar

TimeZone utcTimezone_ = TimeZone.getTimeZone("UTC");
TimeZone _utc = TimeZone.getTimeZone("Zulu");
DateFormat _fo = new SimpleDateFormat("yyyy-MM-dd HH:mm");
_fo.setTimeZone(_utc);
GregorianCalendar gc = new GregorianCalendar(_utc);

System.out.println(gc.getTime());
System.out.println(gc.get(GregorianCalendar.MINUTE));
System.out.println(gc.get(GregorianCalendar.HOUR_OF_DAY));

运行上述代码时输出的示例是:

Mon Sep 16 16:40:37 CST 2013
10
7

在这种情况下,我希望分钟为40(不是10),小时为16(不是7)。 目前我还不理解这一切吗? 感谢。

编辑: 如果我将时区更改为CST(我的本地时区),则分钟和小时仍然不匹配:

TimeZone _utc = TimeZone.getTimeZone("CST");
DateFormat _fo = new SimpleDateFormat("yyyy-MM-dd HH:mm");
_fo.setTimeZone(_utc);
GregorianCalendar gc = new GregorianCalendar(_utc);

System.out.println(gc.getTime());
System.out.println(gc.get(GregorianCalendar.MINUTE));
System.out.println(gc.get(GregorianCalendar.HOUR_OF_DAY));

输出是:

Mon Sep 16 21:23:48 CST 2013
53
6

3 个答案:

答案 0 :(得分:2)

System.out.println(gc.getTime());

此行在您的计算机本地时区打印日历(getTime()返回Date,其中包含与时区相关的纪元以来的ms数,然后隐式toString()调用打印它使用当地时区)。根据结果​​是CST。

System.out.println(gc.get(GregorianCalendar.MINUTE));
System.out.println(gc.get(GregorianCalendar.HOUR_OF_DAY));

这些行打印日历时区中的日历字段。它是"祖鲁"根据你的代码。

By the way, it is strongly recommended not to use three-letters timezones

  

三个字母的时区ID

     

为了与JDK 1.1.x兼容,有些   其他三个字母的时区ID(例如" PST"," CTT"," AST")是   也支持。但是,它们的使用因为相同而被弃用   缩写通常用于多个时区(例如," CST"   可能是美国"中央标准时间"和"中国标准时间"),和   然后,Java平台只能识别其中一个。

答案 1 :(得分:1)

的System.out.println(gc.getTime());以当地时区 - CST打印日期,同时将日历时区设置为GMT。

答案 2 :(得分:1)

避免使用旧的日期时间类

GregorianCalendar是与最早的Java版本捆绑在一起的可怕的日期时间类之一。现在已被 java.time 类所取代,并采用了JSR 310。

ZonedDateTime

不要浪费时间尝试理解GregorianCalendar。该类专门由ZonedDateTime代替。

要与尚未更新为 java.time 的旧代码进行互操作,可以前后转换。查看添加到旧类中的新方法。

ZonedDateTime zdt = myGregCal.toZonedDateTime() ;

…和…

GregorianCalendar myGregCal = GregorianCalendar.from( zdt ) ;

Table of date-time types in Java, both modern and legacy

询问一天中的时间

捕获在特定时区看到的当前时刻。

ZoneId z = ZoneId.of( "America/Chicago" ) ;  // CST is ambiguous, and not a real time zone. Use proper `Continent/Region` names. 
ZonedDateTime zdt = ZonedDateTime.now( z ) ;

或者,让我们使用您的特定示例:2013年9月16日星期一CST。

LocalDate ld = LocalDate.of( 2013 , Month.SEPTEMBER , 16 ) ;
LocalTime lt = LocalTime.of( 16 , 40 , 37 ) ;

在伪区域CST中,您是指中国标准时间还是中部标准时间?我会猜测第二个,因此是一个时区,例如America/ChicagoAmerica/Winnipeg

Continent/Region的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用2-4个字母的缩写,例如ESTCSTIST,因为它们不是真正的时区,不是标准化的,甚至不是唯一的( !)。

ZoneId z = ZoneId.of( "America/Chicago" ) ;

将所有内容放在一起确定一个时刻,即时间轴上的特定点。

ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;
  

zdt.toString():2013-09-16T16:40:37-05:00 [美国/芝加哥]

现在,您可以像在“问题”中所做的那样,询问每日时段。

int hourZdt = zdt.getHour() ;
int minuteZdt = zdt.getMinute() ;
  

hourZdt:16

     

minuteZdt:40

要调整为UTC,请提取Instant对象。根据定义,Instant始终采用UTC。

Instant instant = zdt.toInstant() ;
  

instant.toString():2013-09-16T21:40:37Z

Instant类是 java.time 的基本构建块,功能有限。让我们转换为OffsetDateTime以获得更大的灵活性。我们通过指定常量UTC,为ZoneOffset.UTC本身指定了零小时分分钟秒的UTC偏移量。

OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
  

odt.toString():2013-09-16T21:40:37Z

询问时间部分。

int hourOdt = odt.getHour() ;
int minuteOdt = odt.getMinute() ;
  

hourOdt:21

     

minuteOdt:40

请参阅此code run live at IdeOne.com


Table of which java.time library to use with which version of Java or Android