如何在java8中获取默认的ZoneOffset?

问题描述 投票:31回答:1

用java8我们知道使用ZoneId.default()可以获得系统默认的ZoneId,但是如何获得默认的ZoneOffset

我看到ZoneId有一些“规则”,每个规则有一个ZoneOffset,这是否意味着ZoneId可能有一个以上的ZoneOffset

java java-8 timezone timezone-offset
1个回答
112
投票

tl;dr

OffsetDateTime.now().getOffset()

但您可能应该使用时区而不是仅仅偏离UTC。

ZoneId.systemDefault() 

Offset versus Time Zone

offset-from-UTC只是一小时,几分钟和几秒钟 - 仅此而已。

time zone是特定地区人民使用的偏移的过去,现在和未来变化的历史。时区有一组规则来处理诸如Daylight Saving Time (DST)之类的异常,这些异常会导致特定时间段内偏移的变化。

时区=(偏移历史+异常规则)

因此,在知道时更好地使用区域。

任何地区的偏移量随时间而变化。例如,DST in the United States将偏移量移动一个小时,大约一半,然后在一年的另一半中将该小时恢复到偏移量。时区的整个目的是记录偏移量的变化。

因此,在没有日期时间的情况下要求偏移是没有意义的。在America/Los_Angeles,例如在今年的部分时间,补偿是-08:00,但在夏令时期间的另一部分是-07:00

OffsetDateTime

所以让我们指定一个时刻作为OffsetDateTime,然后提取ZoneOffset

OffsetDateTime odt = OffsetDateTime.now ();
ZoneOffset zoneOffset = odt.getOffset ();

odt.toString():2017-01-02T15:19:47.162-08:00

zoneOffset.toString(): - 08:00

now方法实际上是隐式应用JVM的当前默认时区。我建议您始终通过指定所需/预期的时区来明确说明。即使您想要当前的默认区域,也要明确说明您的意图。消除关于您是否打算默认或未能考虑时区的模糊性,因为程序员经常会这样做。打电话给ZoneId.systemDefault

OffsetDateTime odt = OffsetDateTime.now ( ZoneId.systemDefault () );
ZoneOffset zoneOffset = odt.getOffset ();

ZoneId.systemDefault()。toString():America / Los_Angeles

自:2017-01-02T15:19:47.162-08:00

zoneOffsetOfOdt:-08:00

关于依赖于默认区域的注意事项:此默认值可随时由JVM中任何线程中的任何代码更改。如果重要,请询问用户预期的时区。

您可以将偏移量作为总秒数询问偏移量。

int offsetSeconds = zoneOffset.getTotalSeconds ();

offsetSeconds:-28800

ZonedDateTime

另一个例子:也许你想知道今年圣诞节在魁北克会有什么补偿。指定时区America/Montreal,得到一个ZonedDateTime,请求它作为ZoneOffset对象的偏移量。

ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate ld = LocalDate.of( 2017 , 12 , 25 );
ZonedDateTime zdtXmas = ld.atStartOfDay( z );
ZoneOffset zoneOffsetXmas = zdtXmas.getOffset();

zdtXmas.toString():2017-12-25T00:00-05:00 [美国/蒙特利尔]

zoneOffsetXmas.toString(): - 05:00

zoneOffsetXmas.getTotalSeconds(): - 18000

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

ZoneId

正如yanys的评论中所建议的,你可以通过传递一个时刻作为ZoneId来查询ZoneOffset特定的InstantInstant类代表UTC时间轴上的一个时刻,分辨率为nanoseconds(小数部分最多九(9)位)。

这只是通往同一目的地的另一条路线。就像上面讨论的OffsetDateTimeZonedDateTime一样,我们指定(a)时区,(b)片刻。

Instant instant = zdtXmas.toInstant();
ZoneOffset zo = z.getRules().getOffset( instant );

对于ZoneId:美国/蒙特利尔立即:2017-12-25T05:00:00Z ZoneOffset为:-05:00

看看所有这些例子'code live at IdeOne.com

ZoneOffset.systemDefault - 错误或功能?

ZoneOffset类是ZoneId的子类,记录为继承systemDefault方法。但是,这实际上并不起作用。

ZoneOffset zoneOffset = ZoneOffset.systemDefault() ;  // Fails to compile.

错误:不兼容的类型:ZoneId无法转换为ZoneOffset

不确定这个编译失败是错误还是功能。如上所述,对于我来说,要求使用日期时间的默认偏移似乎没有意义,所以也许ZoneOffset.systemDefault确实会失败。但文档应该这样说,并附上解释。

我试图提交一个关于文档无法解决此问题的错误,但放弃了,无法确定在何处以及如何提交此类错误报告。


About java.time

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

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

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

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

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展了java.time。该项目是未来可能添加到java.time的试验场。你可能会在这里找到一些有用的类,如IntervalYearWeekYearQuartermore

© www.soinside.com 2019 - 2024. All rights reserved.