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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32626733/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 12:52:04  来源:igfitidea点击:

Is there any way to convert ZoneId to ZoneOffset in java 8?

javajava-8java-time

提问by Renkai

I have an epoch second and a zoneId,by method1.It can be convert to LocalDateTime with system default zoneId,but I don't find the way to convert epoch second to LocalDateTime by method2,because there is no ZoneOffset.systemDefault.I think it's obscure.

我有一个纪元秒和一个 zoneId,通过方法 1。它可以转换为具有系统默认 zoneId 的 LocalDateTime,但我没有找到通过方法 2 将纪元秒转换为 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

回答by Jon Skeet

As the documentationsays, "This is primarily intended for low-level conversions rather than general application usage."

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

Going via Instantmakes perfect sense to me - your epoch second is effectively a different representation of an Instant, so convert to an Instantand then convert that into a particular time zone.

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

回答by GreyFairer

There is no one-to-one mapping. A ZoneId defines a geographic extent in which a set of different ZoneOffsets is used over time. If the timezone uses daylight saving time, its ZoneOffset will be different between summer and winter.

没有一对一的映射。ZoneId 定义了一个地理范围,其中随时间使用一组不同的 ZoneOffset。如果时区使用夏令时,则其 ZoneOffset 将在夏季和冬季不同。

Furthermore, the daylight saving time rules may have changed over time, so the ZoneOffset could be different for e.g. 13/10/2015 compared to 13/10/1980.

此外,夏令时规则可能会随着时间的推移而改变,因此例如 13/10/2015 与 13/10/1980 相比,ZoneOffset 可能会有所不同。

So you can only find the ZoneOffset for a ZoneId on a particular Instant.

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

See also https://en.wikipedia.org/wiki/Tz_database

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

回答by Stanislav Bashkyrtsev

Here is how you can get ZoneOffsetfrom ZoneId:

这里是你如何能得到ZoneOffset来自ZoneId

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

NB: ZoneIdcan have different offset depending on point in time and the history of the particular place. So choosing different Instants would result in different offsets.

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

NB2: ZoneId.of()can return a ZoneOffsetinstead of ZoneIdif UTC+3/GMT+2/etc is passed as opposed to a time zone like Africa/Cairo. So if UTC/GMT offsets are passed then historical/geographical/daylight-saving information of the Instantwon't be taken into account - you'll simply work with the specified offset.

NB2:ZoneId.of()可以返回 aZoneOffset而不是ZoneIdif UTC+3/ GMT+2/etc 被传递,而不是像Africa/Cairo. 因此,如果传递 UTC/GMT 偏移量,Instant则不会考虑历史/地理/夏令时信息- 您只需使用指定的偏移量即可。

回答by Basil Bourque

tl;dr

tl;博士

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

…of current default time zone…

…当前默认时区…

ZonedDateTime.now( 
    ZoneId.systemDefault() 
)

Details

细节

The Answer by Stanislav Bshkyrtsevcorrectly and directly answers your Question.

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

But, there are larger issues involved, as suggested in the Answer by Jon Skeet.

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

LocalDateTime

LocalDateTime

I don't find the way to convert epoch second to LocalDateTime

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

LocalDateTimepurposely has no concept of time zone or offset-from-UTC. Not likely what you want. The Local…means anylocality, not any one particular locality. This class does notrepresent a moment, only potentialmoments along a range of about 26-27 hours (the range of time zones around the globe).

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

Instant

Instant

No need to start with epoch seconds if you are trying to get current time. Get the current Instant. The Instantclass represents a moment on the timeline in UTCwith a resolution of nanoseconds(up to nine (9) digits of a decimal fraction).

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

Instant instant = Instant.now();

Inside of that Instantis a count of nanoseconds-from-epoch. But we do not really care.

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

ZonedDateTime

ZonedDateTime

If you want to see that moment through the lens of a particular region's wall-clock time, apply a ZoneIdto get a ZonedDateTime.

如果您想通过特定区域挂钟时间的镜头看到那一刻,请应用 aZoneId以获得ZonedDateTime.

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

As a shortcut, you can do directly to the ZonedDateTime.

作为一种快捷方式,您可以直接对ZonedDateTime.

ZonedDateTime zdt = ZonedDateTime.now( z );  

A ZonedDateTimehas an Instantwithin it. Call zdt.toInstant()to get the same moment in time as a basic value in UTC. Same number of nanoseconds-since-epoch either way, as a ZonedDateTimeor as a Instant.

A 里面ZonedDateTime有一个Instant。调用zdt.toInstant()以获取与UTC 中的基本值相同的时刻。无论哪种方式,自纪元以来的纳秒数都与 aZonedDateTime或 a 相同Instant

Seconds-since-epoch given

给定的时代以来的秒数

If you are given a count of seconds-since-epoch, and the epoch is the first moment of 1970 in UTC(1970-01-01T00:00:00Z), then feed that number to Instant.

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

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


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

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



About java.time

关于java.time

The java.timeframework is built into Java 8 and later. These classes supplant the troublesome old legacydate-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

java.time框架是建立在Java 8和更高版本。这些类取代了麻烦的旧的遗留日期时间类,例如java.util.Date, Calendar, & SimpleDateFormat

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

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

The Joda-Timeproject, now in maintenance mode, advises migration to the java.timeclasses.

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

You may exchange java.timeobjects directly with your database. Use a JDBC drivercompliant with JDBC 4.2or later. No need for strings, no need for java.sql.*classes.

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

Where to obtain the java.time classes?

从哪里获得 java.time 类?

The ThreeTen-Extraproject extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多

回答by gknauth

I hope the first two lines of my solution below are helpful. My problem was I had a LocalDateTimeand the name of a time zone, and I needed an instantso I could build a java.util.Date, because that's what MongoDB wanted. My code is Scala, but it's so close to Java here I think there should be no problem understanding it:

我希望下面我的解决方案的前两行有帮助。我的问题是我有一个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)

回答by Jelmer

The following returns the amount of time in milliseconds to add to UTC to get standard time in this time zone:

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

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