我正在尝试设置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/Montreal
、 Africa/Casablanca
或 Pacific/Auckland
。切勿使用 3-4 个字母的缩写,例如 EST
或 IST
,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!(。
ZoneId z = ZoneId.of( "Australia/Brisbane" ) ;
在该区域的人们看到的挂钟时间中捕捉当前时刻。
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
覆盖一天中的小时。
ZonedDateTime zdt23 = zdt.withHour( 23 ) ;
关于 java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧传统日期时间类,如java.util.Date
、Calendar
和SimpleDateFormat
。
Joda-Time 项目现在处于维护模式,建议迁移到 java.time 类。
要了解更多信息,请参阅 Oracle 教程。并搜索堆栈溢出以获取许多示例和解释。规范为 JSR 310。
使用符合 JDBC 4.2 或更高版本的 JDBC 驱动程序,您可以直接与数据库交换 java.time 对象。不需要字符串或java.sql.*类。
从哪里获得java.time类?
- Java SE
- 8、Java SE 9 及更高版本
- 内置。
- 具有捆绑实现的标准 Java API 的一部分。
- Java 9添加了一些小功能和修复。
Java SE - 6 和 Java SE 7
- 许多java.time功能在ThreeTen-Backport中向后移植到Java 6和7。
- 人造人
- java.time 类的 Android 捆绑包实现的更高版本。
- 对于早期的Android,ThreeTenABP项目适应了ThreeTen-Backport(如上所述(。请参阅如何使用ThreeTenABP...。
ThreeTen-Extra项目通过额外的类扩展了java.time。这个项目是未来可能添加到java.time的试验场。你可以在这里找到一些有用的类,如Interval
、YearWeek
、YearQuarter
等。