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

时间:2015-09-17 09:21:40

标签: java java-8 java-time

我有一个epoch秒和一个zoneId,方法1.它可以转换为LocalDateTime系统默认的zoneId,但我找不到方法将第二个转换为LocalDateTime by method2,因为没有{{1我认为这很模糊。

ZoneOffset.systemDefault

7 个答案:

答案 0 :(得分:74)

以下是ZoneOffset来自ZoneId的方法:

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

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

答案 1 :(得分:35)

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

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

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

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

答案 2 :(得分:16)

TL;博士

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

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

ZonedDateTime.now( 
    ZoneId.systemDefault() 
)

详细

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 - 来自时代的计数。但我们并不在乎。

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 ) ;

关于 java.time

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

要了解详情,请参阅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

答案 3 :(得分:8)

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

经过Instant对我来说非常有意义 - 您的纪元秒实际上是Instant的不同表示,因此转换为Instant然后将其转换为特定时区

答案 4 :(得分: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)

答案 5 :(得分:0)

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

TimeZone.getTimeZone(ZoneId.of("Europe/Amsterdam")).getRawOffset()

答案 6 :(得分:0)

我有一个纪元和一个zoneId。有什么办法可以在Java 8中将ZoneId转换为ZoneOffset?

  1. 从纪元秒和区域ID获取ZonedDateTime
  2. ZoneOffset获取ZonedDateTime

演示:

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;

public class Main {
    public static void main(String[] args) {
        // Get ZonedDateTime from epoch second and Zone Id
        ZonedDateTime zdt = Instant.ofEpochSecond(1597615462L).atZone(ZoneId.of("Europe/London"));

        // Get ZoneOffset from ZonedDateTime
        ZoneOffset offset = zdt.getOffset();

        System.out.println(offset);
    }
}

输出:

+01:00