有什么方法可以在 Java 8 中将 ZoneId 转换为 ZoneOffset 吗?

新手上路,请多包涵

我有一个纪元秒和一个 zoneId (见下面的 method1 )。

它可以转换为 LocalDateTime 使用系统默认的 zoneId,但我找不到将纪元秒转换为 LocalDateTime 的方法(参见 method2 ),因为没有 ZoneOffset.systemDefault 。我认为这很晦涩。

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

val epochSecond = System.currentTimeMillis() / 1000

// method1
LocalDateTime.ofInstant(Instant.ofEpochSecond(epochSecond), ZoneId.systemDefault())

// method2
LocalDateTime.ofEpochSecond(epochSecond, 0, ZoneOffset.MAX)


笔记

上面提供的源代码是 Scala

原文由 Renkai 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 2.1k
2 个回答

以下是如何从 ZoneOffset 获得 ZoneId

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

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

NB2: ZoneId.of() can return a ZoneOffset instead of ZoneId if UTC+3 / GMT+2 /etc is passed as opposed到像 Africa/Cairo 这样的时区。因此,如果传递了 UTC/GMT 偏移量,则不会考虑 Instant 的历史/地理/夏令时信息 - 您只需使用指定的偏移量即可。

原文由 Stanislav Bashkyrtsev 发布,翻译遵循 CC BY-SA 4.0 许可协议

tl;博士

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

…当前默认时区…

 ZonedDateTime.now(
    ZoneId.systemDefault()
)

细节

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

但是,正如 Jon Skeet 在 Answer 中所建议的那样,还涉及到更大的问题。

LocalDateTime

我找不到将纪元秒转换为 LocalDateTime 的方法

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

Instant

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

 Instant instant = Instant.now();

在里面 Instant纳秒 数-从纪元开始。但我们并不真正关心。

另请参阅 Instant 和 LocalDateTime 之间的区别是什么?

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 基本值相同的时刻。自纪元以来的纳秒数相同,作为 ZonedDateTime 或作为 Instant

给定纪元以来的秒数

如果你得到了自纪元以来的秒数,并且纪元是 UTC 中 1970 年的第一个时刻( 1970-01-01T00:00:00Z ),然后将该数字提供给 Instant

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


Java 中的日期时间类型表,包括现代的和传统的。


关于 java.time

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

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

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

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

在哪里获取 java.time 类?

ThreeTen-Extra 项目用附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可能会在这里找到一些有用的类,例如 IntervalYearWeekYearQuarter 等等

原文由 Basil Bourque 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题