有没有办法在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
Is there any way to convert ZoneId to ZoneOffset in java 8?
提问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 Instant
makes perfect sense to me - your epoch second is effectively a different representation of an Instant
, so convert to an Instant
and 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。
回答by Stanislav Bashkyrtsev
Here is how you can get ZoneOffset
from ZoneId
:
这里是你如何能得到ZoneOffset
来自ZoneId
:
Instant instant = Instant.now(); //can be LocalDateTime
ZoneId systemZone = ZoneId.systemDefault(); // my timezone
ZoneOffset currentOffsetForMyZone = systemZone.getRules().getOffset(instant);
NB: ZoneId
can 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 ZoneOffset
instead of ZoneId
if 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 Instant
won't be taken into account - you'll simply work with the specified offset.
NB2:ZoneId.of()
可以返回 aZoneOffset
而不是ZoneId
if 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 的方法
LocalDateTime
purposely 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 Instant
class 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 Instant
is 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 ZoneId
to 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 ZonedDateTime
has an Instant
within 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 ZonedDateTime
or 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 ) ;
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 类?
- Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
- Java 9 adds some minor features and fixes.
- Java SE 6and Java SE 7
- Most of the java.timefunctionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
- Android
- Later versions of Android bundle implementations of the java.timeclasses.
- For earlier Android (<26), the ThreeTenABPproject adapts ThreeTen-Backport(mentioned above). See How to use ThreeTenABP….
- Java SE 8、Java SE 9、Java SE 10、Java SE 11及更高版本 - 标准 Java API 的一部分,具有捆绑实现。
- Java 9 添加了一些小功能和修复。
- Java SE 6和Java SE 7
- 大部分java.time功能在ThreeTen-Backport中向后移植到 Java 6 & 7 。
- 安卓
- java.time类的更高版本的 Android 捆绑实现。
- 对于早期的 Android(<26),ThreeTenABP项目采用了ThreeTen-Backport(上面提到过)。请参阅如何使用ThreeTenABP ...。
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 的试验场。你可能在这里找到一些有用的类,比如Interval
,YearWeek
,YearQuarter
,和更多。
回答by gknauth
I hope the first two lines of my solution below are helpful. My problem was I had a LocalDateTime
and the name of a time zone, and I needed an instant
so 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()