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

Ren*_*kai 63 java java-8 java-time

我有一个epoch秒和一个zoneId,方法1.它可以转换为LocalDateTime与系统默认的zoneId,但我找不到方法将第二个转换为LocalDateTime by method2,因为没有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
Run Code Online (Sandbox Code Playgroud)

Sta*_*sev 85

以下是您可以获得ZoneOffset的方式ZoneId:

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

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

  • 嗯..回答这个问题?:)添加说明以防人们直接回答问题而不阅读问题. (13认同)
  • 请提供代码的上下文. (2认同)

Gee*_*nte 39

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

此外,夏令时规则可能随着时间的推移而发生变化,因此ZoneOffset可能与13/10/2015相比有所不同,例如13/10/2019.

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

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

  • 我知道,但它是如何完成的?如果我知道LocaDate并且有一个ZoneId,我该如何将它转换为ZoneOffset.我的用例是一个包含时间和区域的字符串.我想将字符串解析为OffsetTime,而不删除区域信息. (8认同)

Bas*_*que 22

TL;博士

ZonedDateTime.now( 
    ZoneId.of( "America/Montreal" ) 
)
Run Code Online (Sandbox Code Playgroud)

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

ZonedDateTime.now( 
    ZoneId.systemDefault() 
)
Run Code Online (Sandbox Code Playgroud)

细节

由斯坦尼斯Bshkyrtsev回答正确,直接回答你的问题.

但是,正如Jon Skeet回答所建议的那样,涉及的问题更多.

LocalDateTime

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

LocalDateTime故意没有时区概念或从UTC偏移.不太可能你想要的.这Local…意味着任何地方,而不是任何一个特定的地方.该类也不能代表同一时刻只能有潜力沿着范围约26-27小时(时区的世界各地的范围内)的时刻.

Instant

如果您想获得当前时间,则无需以纪元秒开始.获取最新信息Instant.该Instant级表示时间轴上的时刻UTC,分辨率为纳秒(最多9个(9)小数的位数).

Instant instant = Instant.now();
Run Code Online (Sandbox Code Playgroud)

其中的内容Instant是从纳秒开始的计数.但我们并不在乎.

ZonedDateTime

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

ZoneId z = ZoneId.of( "Europe/Paris" );
ZonedDateTime zdt = instant.atZone( z );
Run Code Online (Sandbox Code Playgroud)

作为捷径,你可以直接做到ZonedDateTime.

ZonedDateTime zdt = ZonedDateTime.now( z );  
Run Code Online (Sandbox Code Playgroud)

A里面ZonedDateTime有一个Instant.呼叫zdt.toInstant()以与UTC中的基本值相同的时刻.相同数量的纳秒 - 自上世纪以来,作为a ZonedDateTime或a Instant.

给出了秒数以来的时代

如果给你一个秒 - 自 - 纪元的计数,并且纪元是UTC(1970-01-01T00:00:00Z)中的1970年的第一个时刻,那么将该数字提供给Instant.

long secondsSinceEpoch = 1_484_063_246L ;
Instant instant = Instant.ofEpochSecond( secondsSinceEpoch ) ;
Run Code Online (Sandbox Code Playgroud)

关于java.time

java.time框架是建立在Java 8和更高版本.这些类取代麻烦的老传统日期时间类,如java.util.Date,Calendar,和SimpleDateFormat.

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

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

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

从哪里获取java.time类?

ThreeTen-额外项目与其他类扩展java.time.该项目是未来可能添加到java.time的试验场.您可以在此比如找到一些有用的类Interval,YearWeek,YearQuarter,和更多.


gkn*_*uth 9

我希望下面的解决方案的前两行是有用的.我的问题是我有一个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)
Run Code Online (Sandbox Code Playgroud)


Jon*_*eet 8

正如文档所说,"这主要用于低级转换,而不是一般的应用程序使用."

通过Instant对我来说非常有意义 - 你的时代秒实际上是一个不同的表示Instant,所以转换为a Instant然后将其转换为特定的时区.