Java GregorianCalendar change TimeZone



我正在尝试设置HOUR_OF_DAY字段并更改公历日期对象的时区。

GregorianCalendar date = new GregorianCalendar(TimeZone.getTimeZone("GMT+10"));
System.out.println("HOUR: " + date.get(Calendar.HOUR_OF_DAY));
date.set(Calendar.HOUR_OF_DAY, 23);
//date.get(Calendar.HOUR_OF_DAY);
date.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println("HOUR: " + date.get(Calendar.HOUR_OF_DAY));

输出:

HOUR: 16
HOUR: 23

由于某种原因,HOUR_OF_DAY值在设置不同的时区后不会更改。但是,如果我取消对 date.get 的评论HOUR_OF_DAY,一切都完全按照应有的方式工作

GregorianCalendar date = new GregorianCalendar(TimeZone.getTimeZone("GMT+10"));
System.out.println("HOUR: " + date.get(Calendar.HOUR_OF_DAY));
date.set(Calendar.HOUR_OF_DAY, 23);
date.get(Calendar.HOUR_OF_DAY); // uncommenting this line will is changing the output
date.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println("HOUR: " + date.get(Calendar.HOUR_OF_DAY));

输出:

HOUR: 16
HOUR: 13

这怎么可能?为什么 .get 方法会改变对象行为?

GregorianCalendar 类从 Calendar 继承其get方法,具有以下副作用:

在宽松模式下,所有日历字段都会规范化。

这意味着在Calendar对象上调用get时,将重新计算time值和所有字段。 这可能会导致一些不可预测的行为,特别是当与 setTimeZone 结合使用时,它有一些记录在案的错误行为。

tl;dr

OffsetDateTime.now( ZoneOffset.ofHours( 10 )  ).withHour( 23 )

避免使用传统的日期时间课程

包括GregorianCalendar在内的旧日期时间类令人困惑。 笨拙,设计不佳的混乱。避免它们。现在被java.time类取代。具体来说,GregorianCalendar替换为 ZonedDateTime .

从 UTC 偏移

您显然想要一个比 UTC 早十小时的偏移量。定义所需的偏移量。

ZoneOffset offset = ZoneOffset.ofHours( 10 ) ;

offset.toString((: +10:00

获取当前时刻作为具有该偏移量的OffsetDateTime

OffsetDateTime odt = OffsetDateTime.now( offset ) ;

odt.toString((: 2018-02-15T16:44:44.216642+10:00

您希望覆盖要23的小时。

OffsetDateTime odt23 = odt.withHour( 23 ) ;

odt23.toString((: 2018-02-15T23:44:44.216642+10:00

时区

我正在尝试设置HOUR_OF_DAY字段并更改公历日期对象的时区。

不,您正在更改与 UTC 的偏移量,而不是时区。

如果您确定预期区域,最好使用时区而不是仅仅偏移量。时区是某个地区人民使用的偏移量的过去、现在和未来变化的历史记录。使用时区,您始终可以确定偏移量,反之则不然。

continent/region 的格式指定正确的时区名称,例如 America/MontrealAfrica/CasablancaPacific/Auckland 。切勿使用 3-4 个字母的缩写,例如 ESTIST,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!(。

ZoneId z = ZoneId.of( "Australia/Brisbane" ) ;  

在该区域的人们看到的挂钟时间中捕捉当前时刻。

ZonedDateTime zdt = ZonedDateTime.now( z ) ;

覆盖一天中的小时。

ZonedDateTime zdt23 = zdt.withHour( 23 ) ;

关于 java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧传统日期时间类,如java.util.DateCalendarSimpleDateFormat

Joda-Time 项目现在处于维护模式,建议迁移到 java.time 类。

要了解更多信息,请参阅 Oracle 教程。并搜索堆栈溢出以获取许多示例和解释。规范为 JSR 310。

使用符合 JDBC 4.2 或更高版本的 JDBC 驱动程序,您可以直接与数据库交换 java.time 对象。不需要字符串或java.sql.*类。

从哪里获得java.time类?

    Java SE
  • 8Java SE 9 及更高版本
    • 内置。
    • 具有捆绑实现的标准 Java API 的一部分。
    • Java 9添加了一些小功能和修复。
  • Java SE
  • 6Java SE 7
    • 许多java.time功能在ThreeTen-Backport中向后移植到Java 6和7。
  • 人造人
    • java.time 类的 Android 捆绑包实现的更高版本。
    • 对于早期的Android,ThreeTenABP项目适应了ThreeTen-Backport(如上所述(。请参阅如何使用ThreeTenABP...

ThreeTen-Extra项目通过额外的类扩展了java.time。这个项目是未来可能添加到java.time的试验场。你可以在这里找到一些有用的类,如IntervalYearWeekYearQuarter等。

相关内容

  • 没有找到相关文章

最新更新