2

我在 java 中使用 Calendar 类并且遇到了麻烦。我有这个代码

Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("NZST"));
System.out.println("Calendar.HOUR_OF_DAY = " + calendar.get(Calendar.HOUR_OF_DAY));
System.out.println("Calendar.HOUR = " + calendar.get(Calendar.HOUR));
System.out.println("calendar.getTime() = " + calendar.getTime());

我希望它能够输出

Calendar.HOUR_OF_DAY = 17
Calendar.HOUR = 5
calendar.getTime() = Sat Aug 08 17:45:53 NZST 2020

但相反它输出

Calendar.HOUR_OF_DAY = 5
Calendar.HOUR = 5
calendar.getTime() = Sat Aug 08 17:45:53 NZST 2020

那么为什么 HOUR_OF_DAY 和 HOUR 返回相同的东西,但是 calendar.getTime() 显示了正确的 HOUR_OF_DAY。他们都使用NZST。

4

2 回答 2

3

他们都使用NZST。

不,他们不是,虽然我明白你为什么认为他们是。

第一个实际上是使用 UTC,因为“NZST”不是有效的时区 ID。遗憾的是,TimeZone.getTimeZone当您使用无效 ID 显示它时不会引发异常,但现在无法更改:(

calendar.getTime()正在返回一个Date参考,并且Date没有时区,因此它在您的系统本地时区打印 - 这恰好是新西兰。

如果您将第一行代码更改为使用实时时区 ID,它的行为与您预期的一样:

Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("Pacific/Auckland"));

一些缩写(如NZST )在 Java 中识别为时区 ID,但最好使用完整的IANA 时区ID,如“Pacific/Auckland”。

于 2020-08-08T05:56:32.400 回答
1

tl;博士

ZonedDateTime
.now( 
    ZoneId.of( "Pacific/Auckland" ) 
) 
.getHour()

细节

Jon Skeet的答案是正确的。此外,您使用的糟糕的类在几年前被JSR 310 中定义的java.time类所取代。

java.time中的ZoneId类替换了类。这个类实现了 Jon Skeet 的回答中的愿望:如果你给它一个错误的区域 ID,比如,它会抛出一个异常。TimeZoneZoneIdNZST

java.time

ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;  // Specify a time zone. A history of past, present, and future changes to the offset-from-UTC used by the people of a particular region. 
ZonedDateTime zdt = ZonedDateTime.now( z ) ;  // Capture the current time as seen in a particular time zone.
int hour = zdt.getHour() ;                    // Extract the hour of he day.
于 2020-08-08T06:14:27.397 回答