有没有办法在java 8中将ZoneId转换为ZoneOffset?

问题描述 投票:57回答:6

我有一个epoch秒和一个zoneId,方法1.它可以用系统默认的zoneId转换为LocalDateTime,但我找不到方法2将epoch第二个转换为LocalDateTime,因为没有ZoneOffset.systemDefault。我认为它是模糊的。

import java.time.{Instant, LocalDateTime, ZoneId, ZoneOffset}

val epochSecond = System.currentTimeMillis() / 1000

LocalDateTime.ofInstant(Instant.ofEpochSecond(epochSecond), ZoneId.systemDefault())//method1
LocalDateTime.ofEpochSecond(epochSecond, 0, ZoneOffset.MAX)//method2
java java-8 java-time
6个回答
78
投票

以下是如何从ZoneOffset获得ZoneId

Instant instant = Instant.now(); //can be LocalDateTime
ZoneId systemZone = ZoneId.systemDefault(); // my timezone
ZoneOffset currentOffsetForMyZone = systemZone.getRules().getOffset(instant);

注意:根据时间点和特定地点的历史,ZoneId可以有不同的偏移量。因此,选择不同的Instants会导致不同的偏移。


37
投票

没有一对一的映射。 ZoneId定义了一段时间内使用一组不同ZoneOffsets的地理范围。如果时区使用夏令时,则其ZoneOffset在夏季和冬季之间会有所不同。

此外,夏令时规则可能随着时间的推移而发生变化,因此ZoneOffset可能会因此而异。 2015年10月13日与1980年10月13日相比。

因此,您只能在特定的Instant上找到ZoneId的ZoneOffset。

另见https://en.wikipedia.org/wiki/Tz_database


20
投票

tl;dr

ZonedDateTime.now( 
    ZoneId.of( "America/Montreal" ) 
)

...当前默认时区...

ZonedDateTime.now( 
    ZoneId.systemDefault() 
)

Details

Answer by Stanislav Bshkyrtsev正确并直接回答您的问题。

但是,正如Answer by Jon Skeet所建议的那样,涉及的问题更多。

LocalDateTime

我没有找到将epoch second转换为LocalDateTime的方法

LocalDateTime故意没有时区概念或从UTC偏移。不太可能你想要的。 Local…意味着任何地方,而不是任何一个特定的地方。这个类不代表片刻,只是在大约26-27小时(全球各个时区范围)范围内的潜在时刻。

Instant

如果您想获得当前时间,则无需以纪元秒开始。获取当前的InstantInstant类代表UTC时间轴上的一个时刻,分辨率为nanoseconds(小数部分最多九(9)位)。

Instant instant = Instant.now();

Instant内部是nanoseconds从epoch的计数。但我们并不在乎。

ZonedDateTime

如果你想通过特定区域的挂钟时间镜头看到那个时刻,请使用ZoneId来获得ZonedDateTime

ZoneId z = ZoneId.of( "Europe/Paris" );
ZonedDateTime zdt = instant.atZone( z );

作为捷径,您可以直接进行ZonedDateTime

ZonedDateTime zdt = ZonedDateTime.now( z );  

一个ZonedDateTime里面有一个Instant。打电话给zdt.toInstant()以获得与UTC基本值相同的时刻。相同数量的纳秒 - 自上世纪以来,作为ZonedDateTimeInstant

给出了秒数以来的时代

如果给你一个秒数 - 从纪元开始,并且这个纪元是1970年UTC1970-01-01T00:00:00Z)的第一个时刻,那么将这个数字提供给Instant

long secondsSinceEpoch = 1_484_063_246L ;
Instant instant = Instant.ofEpochSecond( secondsSinceEpoch ) ;

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


About java.time

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

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

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

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

从哪里获取java.time类?

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


8
投票

正如documentation所说,“这主要用于低级转换,而不是一般的应用程序使用。”

经过Instant对我来说非常有意义 - 你的第二纪元实际上是Instant的不同表现形式,所以转换为Instant然后将其转换为特定的时区。


7
投票

我希望下面的解决方案的前两行是有用的。我的问题是我有一个LocalDateTime和一个时区的名称,我需要一个instant所以我可以建立一个java.util.Date,因为这是MongoDB想要的。我的代码是Scala,但它与Java如此接近,我认为理解它应该没有问题:

val zid = ZoneId.of(tzName)                                // "America/Los_Angeles"
val zo: ZoneOffset = zid.getRules.getOffset(localDateTime) // ⇒ -07:00
                                         // 2017-03-16T18:03

val odt = OffsetDateTime.of(localDateTime, zo) // ⇒ 2017-03-16T18:03:00-07:00
val instant = odt.toInstant                    // ⇒ 2017-03-17T01:03:00Z
val issued = Date.from(instant)

0
投票

以下命令返回添加到UTC以获取此时区的标准时间的时间量(以毫秒为单位):

TimeZone.getTimeZone(ZoneId.of("Europe/Amsterdam")).getRawOffset()
© www.soinside.com 2019 - 2024. All rights reserved.