如何在java8中获得默认的ZoneOffset?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41427384/
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 23:22:20  来源:igfitidea点击:

How to get default ZoneOffset in java8?

javajava-8timezonetimezone-offset

提问by FredSuvn

With java8 we know use ZoneId.default()can get system default ZoneId, but how to get default ZoneOffset?

我们知道使用 java8ZoneId.default()可以获得系统默认值ZoneId,但是如何获得默认值ZoneOffset呢?

I see that a ZoneIdhas some "rules" and each rule has a ZoneOffset, is that means a ZoneIdmay have more than one ZoneOffset?

我看到 aZoneId有一些“规则”,每个规则都有一个ZoneOffset,这是否意味着 aZoneId可能有多个ZoneOffset

采纳答案by Basil Bourque

tl;dr

tl;博士

OffsetDateTime.now().getOffset()

But you likely should be using a time zone rather than a mere offset-from-UTC.

但是您可能应该使用时区,而不仅仅是与 UTC 的偏移量。

ZoneId.systemDefault() 

Offset versus Time Zone

偏移与时区

An offset-from-UTCis merely a number of hour, minutes, and seconds —?nothing more. For example, -08:00means eight hours behind the UTC, and +05:45means five hours and forty-five minutes ahead of UTC.

UTC偏移量仅仅是小时、分钟和秒数——仅此而已。例如,-08:00表示比 UTC 晚 8 小时,+05:45表示比UTC早 5 小时 45 分钟。

A time zoneis a history of past, present, and future changes to the offsetused by the people of a particular region. Anomalies such as Daylight Saving Time (DST)causing shifts in the offset over specific periods of time are tracked over time, in the past as they happened, and in the future when politicians have announced planned changes.

一个时区过去,现在和未来的偏移量变化的历史使用由特定地区的人们。诸如夏令时 (DST) 之类的异常会在特定时间段内导致偏移量的变化,这些异常会随着时间的推移、过去发生的情况以及未来家宣布计划的变化时进行跟踪。

So better to use a zonewhen known.

因此最好在已知时使用区域

The offset for any region varies over time. For example, DST in the United Statesshifts the offset by an hour for about half the year and then restoring that hour back to the offset during the other half of the year. The entire purpose of a time zone is to document those shifts in offset.

任何区域的偏移量随时间变化。例如,美国的 DST 在大约半年的时间内将偏移量移动一个小时,然后在一年的另一半期间将该小时恢复到偏移量。时区的全部目的是记录这些偏移量的变化。

So it really makes no sense to ask for an offset without a date-time. In America/Los_Angeles, for example in part of this year the offset is -08:00but in another part of the year it is -07:00during DST.

因此,在没有 date-time 的情况下要求偏移量确实没有意义。在America/Los_Angeles,例如在今年的一部分偏移-08:00,但在今年的另一部分是-07:00DST期间。

OffsetDateTime

OffsetDateTime

So let's specify a moment as an OffsetDateTime, and then extract the ZoneOffset.

因此,让我们指定一个时刻为OffsetDateTime,然后提取ZoneOffset.

OffsetDateTime odt = OffsetDateTime.now ();
ZoneOffset zoneOffset = odt.getOffset ();

odt.toString(): 2017-01-02T15:19:47.162-08:00

zoneOffset.toString(): -08:00

odt.toString(): 2017-01-02T15:19:47.162-08:00

zoneOffset.toString(): -08:00

That nowmethod is actually applying implicitly the JVM's current default time zone. I suggest you always make that explicit by specifying your desired/expected time zone. Even if you want the current default zone, say so explicitly to make your intentions clear. Eliminate the ambiguity about whether you intended the default or failed to consider time zone as so often happens with programmers. Call ZoneId.systemDefault.

now方法实际上是隐式应用 JVM 的当前默认时区。我建议您始终通过指定所需/预期的时区来明确说明。即使您想要当前的默认区域,也要明确说明以明确您的意图。消除关于您是否打算使用默认值或未考虑时区的歧义,就像程序员经常发生的那样。打电话ZoneId.systemDefault

OffsetDateTime odt = OffsetDateTime.now ( ZoneId.systemDefault () );
ZoneOffset zoneOffset = odt.getOffset ();

ZoneId.systemDefault().toString(): America/Los_Angeles

odt: 2017-01-02T15:19:47.162-08:00

zoneOffsetOfOdt: -08:00

ZoneId.systemDefault().toString(): America/Los_Angeles

ODT:2017-01-02T15:19:47.162-08:00

zoneOffsetOfOdt:-08:00

A caution about depending on the default zone: This default can be changed at any moment by any code in any thread within the JVM. If important, ask the user for their intended time zone.

关于依赖默认区域的注意事项:此默认值可以随时由 JVM 中任何线程中的任何代码更改。如果重要,请询问用户他们想要的时区。

You can ask the offset for its amount of time as a total number of seconds.

您可以询问偏移量作为总秒数的时间量。

int offsetSeconds = zoneOffset.getTotalSeconds ();

offsetSeconds: -28800

偏移秒数:-28800

ZonedDateTime

ZonedDateTime

Another example: Perhaps you want to know what the offset will be on Christmas Day this year in Québec. Specify the time zone America/Montreal, get a ZonedDateTime, ask for its offset as a ZoneOffsetobject.

另一个例子:也许你想知道魁北克今年圣诞节的抵消额是多少。指定 time zone America/Montreal,获取 a ZonedDateTime,请求其偏移量作为ZoneOffset对象。

ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate ld = LocalDate.of( 2017 , 12 , 25 );
ZonedDateTime zdtXmas = ld.atStartOfDay( z );
ZoneOffset zoneOffsetXmas = zdtXmas.getOffset();

zdtXmas.toString(): 2017-12-25T00:00-05:00[America/Montreal]

zoneOffsetXmas.toString(): -05:00

zoneOffsetXmas.getTotalSeconds(): -18000

zdtXmas.toString(): 2017-12-25T00:00-05:00[美国/蒙特利尔]

zoneOffsetXmas.toString(): -05:00

zoneOffsetXmas.getTotalSeconds():-18000

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

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

ZoneId

ZoneId

As suggested in the comment by yanys, you can interrogate a ZoneIdfor a particular ZoneOffsetby passing a moment as an Instant. The Instantclass represents a moment on the timeline in UTCwith a resolution of nanoseconds(up to nine (9) digits of a decimal fraction).

作为由yanys的评论所说,你可以询问一个ZoneId特定ZoneOffset通过传递一个时刻作为Instant。该Instant级表示时间轴上的时刻UTC,分辨率为纳秒(最多小数的9个位数)。

This is just another route to the same destination. Just like with OffsetDateTimeand ZonedDateTimediscussed above, we are specifying (a) a time zone, and (b) a moment.

这只是通往同一目的地的另一条路线。就像用OffsetDateTimeZonedDateTime上面所讨论的,我们指定(一)一个时区,以及(b)一个时刻。

Instant instant = zdtXmas.toInstant();
ZoneOffset zo = z.getRules().getOffset( instant );

For ZoneId: America/Montreal at instant: 2017-12-25T05:00:00Z the ZoneOffset is: -05:00

对于 ZoneId: America/Montreal at Instant: 2017-12-25T05:00:00Z ZoneOffset 是:-05:00

See all these examples' code live at IdeOne.com.

在 IdeOne.com 上实时查看所有这些示例的代码

ZoneOffset.systemDefault– Bug or feature?

ZoneOffset.systemDefault– 错误或功能?

The ZoneOffsetclass, a subclass of ZoneId, is documented as inheriting the systemDefaultmethod. However, this does not actually work.

ZoneOffset类,的一个子类ZoneId,被记录为继承systemDefault方法。但是,这实际上不起作用。

ZoneOffset zoneOffset = ZoneOffset.systemDefault() ;  // Fails to compile.

error: incompatible types: ZoneId cannot be converted to ZoneOffset

错误:不兼容的类型:ZoneId 无法转换为 ZoneOffset

Not sure if this failure-to-compile is a bug or a feature. As discussed above, it does not seem to make sense to me to ever ask for default offset with a date-time, so perhaps the ZoneOffset.systemDefaultshould indeed fail. But the documentation should say so, with an explanation.

不确定这种编译失败是错误还是功能。如上所述,对我来说,要求使用日期时间的默认偏移量似乎没有意义,所以也许ZoneOffset.systemDefault确实应该失败。但是文档应该这样说,并有解释。

I tried to file a bug on the failure of the doc to address this issue, but gave up, unable to determine where and how to file such a bug report.

我试图提交一个关于文档未能解决这个问题的错误,但放弃了,无法确定在哪里以及如何提交这样的错误报告。

Solar Time versus Political time

太阳时间与时间

A bit more about offsets and time zones…

关于偏移量和时区的更多信息......

Solar Timehas been used since pre-history, tracking each day by noting when the sun is directly overhead. Poke a stick in the ground, and watch its shadow. When the shadow is shortest, when the shadow begins to grow rather than shrink, then you know it is now noon. Formalize that with a sundialto track the hours pass.

太阳时自史前时代就已被使用,通过记录太阳何时直接在头顶上来跟踪每一天。在地上戳一根棍子,观察它的影子。当影子最短,当影子开始增长而不是缩小时,你就知道现在是中午了。用日晷将其正式化以跟踪时间过去。

With solar time, as you travel from town to town moving westward, noon arrives a little bit later. Moving eastward, noon arrives a bit sooner. So every town has its own noon, shared only with towns to the north and south along the same longitude.

随着太阳时,当你从一个城镇到另一个城镇向西移动时,中午会晚一点到达。继续往东走,中午来得早一些。所以每个城镇都有自己的中午,只与同一经度的南北城镇共享。

Solar time was largely abandoned in the modern era. As trains, telegraphs, and telephones arrived, so did the need to coordinate temporally. So a point was picked for its near solar time of noon, and a large swath of land so many miles to the west and to the east is declared to all share the same 12:00 on the clock, the same number of hours offset ahead or behind the Greenwich Prime Meridianline. So began the tradition of every train stop displaying prominently a clock to let the town know of the standard timefor their larger region rather than solar time for their own town. Generally, towns in the western edge of that time zone region will see their train station clock read 12:00 a little beforethe sun is overhead. Clocks in towns in the eastern edge of the region read 12:00 a little afterthe sun is overhead.

在现代,太阳时间在很大程度上被放弃了。随着火车、电报和电话的到来,时间协调的需要也随之而来。因此,选择了一个接近太阳时中午的点,并宣布向西和向东如此多英里的大片土地在时钟上共享相同的 12:00,向前偏移相同的小时数或后面格林威治本初子午线线。于是开始了每个火车停靠站显眼地展示时钟的传统,让小镇知道他们更大地区的标准时间,而不是他们自己小镇的太阳时。一般来说,该时区西部边缘的城镇会看到他们的火车站时钟提前一点点显示12:00太阳在头顶。在太阳升起后不久,该地区东部边缘城镇的时钟显示为 12:00 。

Politicians around the world showed a penchant for changing the offset(s) of their jurisdiction. The reasons vary, such diplomacy, war & occupation, and the silliness of Daylight Saving Time (DST). The reasons vary, but their changes come with surprising frequency. A time zone is a name given to a region to track its history of such changes. So an offset-from-UTCis merely a number of hours-minutes-secondsahead or behind the prime meridian. A time zone is much more: a historyof the past, present, and future changes to the offsets of a particular region. While two neighboring regions may today share the same offset-from-UTC, in the past or future they may differ depending on the differing whims or logic of their politicians.

世界各地的政客都表现出改变其管辖范围的倾向。原因各不相同,例如外交、战争和占领,以及夏令时 (DST)的愚蠢。原因各不相同,但它们的变化以惊人的频率出现。时区是一个区域的名称,用于跟踪其此类变化的历史。因此,UTC偏移量只是本初子午线之前或之后的若干小时-分钟-秒。一个时区得多:一个历史的过去,现在和未来的一个特定区域的偏移量的变化。虽然今天两个相邻地区可能共享相同的 UTC 偏移量,但在过去或未来,它们可能会因家的不同想法或逻辑而有所不同。

This means modern time-tracking defined by politicians has little to do with geography. For example, the huge country of India today has a single time zone (offset-from-UTC of +05:30). So solar noon (sun directly over your head) is hours apart in various places across the vast subcontinent. The politicians of India decided this to help unify their diverse democracy. In other examples around the world, we see regions use their time zone as a symbol for international relations such as being different than their offending neighbor country, or choosing the same zone as a neighbor as relations thaw as seen recently in North Korea changing to match South Korea. So, nowadays, solar time is only one of several considerations in time-tracking.

这意味着家定义的现代时间跟踪与地理无关。例如,今天印度这个巨大的国家有一个单一的时区(UTC 偏移量 +05:30)。因此,在广阔的次大陆的各个地方,太阳正午(太阳直接在您的头顶上)相隔数小时。印度的政客们决定这样做是为了帮助统一他们多元化的民主。在世界各地的其他例子中,我们看到地区使用他们的时区作为国际关系的象征,例如与他们的邻国不同,或者选择与邻国相同的区域作为最近在朝鲜看到的关系解冻改变以匹配韩国。因此,如今,太阳时只是时间跟踪的几个考虑因素之一。



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

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

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

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

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 类?

Table of which java.time library to use with which version of Java or Android

哪个 java.time 库与哪个版本的 Java 或 Android 一起使用的表

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 cavok

Depending on your objective, you may be able to bypass ZoneOffsetentirely.

根据您的目标,您可能能够完全绕过ZoneOffset.

Assuming you just need a ZoneOffsetfor e.g. LocalDateTime.ofEpochSecond(), you may replace

假设你只需要一个ZoneOffsetfor eg LocalDateTime.ofEpochSecond(),你可以替换

ZoneOffset offset = OffsetDateTime.now().getOffset();
LocalDateTime dt1 = LocalDateTime.ofEpochSecond(seconds, 0, offset);

with

LocalDateTime dt2 = LocalDateTime.ofInstant(
    Instant.ofEpochSecond(seconds), 
    ZoneId.systemDefault());

where dt1.equals(dt2)is true.

哪里dt1.equals(dt2)true