2

我知道,在给定时区与 GMT 的偏移量的情况下,向用户显示本地时间非常容易(例如,太平洋夏令时间为 -7 小时)。

但是,如果我想在很长一段时间内(比如 1 年)继续显示正确​​的本地时间怎么办。仅给定与 GMT 的偏移量,您不知道用户所在的时区。例如,给定 -7,用户可能居住在美国或加拿大(或其他一些国家/地区)。这些国家/地区在一年中的不同时间点可能有不同的当地时间(例如,如果美国在 3 月更改为白天时间,在 4 月更改为加利福尼亚时间)。

我的问题是,上面的段落是否正确?有没有一种标准的方法来获取 GMT 偏移量并很好地猜测用户所在的时区?

4

1 回答 1

1

您的结论是正确的:没有可靠的方法可以从offset-from-UTC识别时区

对于您的偏移量示例,我在当前列表-07:00中计算了大约三打可能的时区,包括:、、和。America/BoiseAmerica/ChihuahuaAmerica/Edmonton

时区实际上是偏移量的集合,记录了随着时间的推移所做的更改,该偏移量在该区域使用了一定的时间段,然后在另一个特定的时间段内发生了变化。

例如,America/Los_Angeles每年的部分时间有一个偏移量,-08:00而一年的另一部分有-07:00. 因此,该时区每年累积至少两次偏移的历史记录。相比之下,使用时区的相邻区域America/Phoenix没有-07:00累积其偏移量的变化,几十年来一直保持相同的偏移量。

所以我们在偏移量和时区之间存在多对多的关系。偏移量可能出现在一个或多个时区。并且每个时区可以有一个或多个偏移量(已经改变了历史)。

包括时区名称

这就是为什么 java.time 类的设计者ZonedDateTime冒昧地让其toString方法扩展标准ISO 8601格式,仅使用偏移量,并将时区名称附加在方括号中。

例如,2007-12-03T10:15:30+01:00该类生成的不是简单地生成标准格式:,而是附加2007-12-03T10:15:30+01:00[Europe/Paris]了区域Europe/Paris的名称。

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

2007-12-03T10:15:30+01:00[欧洲/巴黎]

我希望这种附加时区名称的做法能够流行起来。缺少时区名称是标准委员会的一个令人惊讶的遗漏,否则这些标准委员会在设计 ISO 8601 方面做得非常出色。

您可以使用业务场景上下文中的线索来猜测时区。但我不建议这样做。猜测是有风险的,特别是因为世界各地的政治家都喜欢频繁地重新定义时区。

世界标准时间

存储、序列化和交换日期时间值的最佳实践通常是调整为UTC。假设日期时间库的tzdata是最新的,调整为 UTC 可提供始终正确且明确的可靠值。

例如,在 Java 中,这意味着使用或提取Instant对象。该类表示UTCInstant时间线上的时刻,分辨率为纳秒(最多九 (9) 位小数)。

Instant instant = Instant.now();

……或者……</p>

ZonedDateTime zdt = ZonedDateTime.now( ZoneId.of( "America/Montreal" ) );
Instant instant = zdt.toInstant();

表示此类值的标准 ISO 8601 格式字符串使用 aZ作为 UTC 的缩写Zulu,表示 UTC。

2007-12-03T09:15:30Z

OffsetDateTime

如果给定一个表示只有偏移量的日期时间的字符串,请将其解析为OffsetDateTime对象。

OffsetDateTime odt = OffsetDateTime.parse( "2007-12-03T10:15:30+01:00" );

odt.toString(): 2007-12-03T10:15:30+01:00

从那里您可以提取一个 UTC 值,一个Instant.

Instant instant = odt.toInstant();

即时.toString(): 2007-12-03T09:15:30Z

或者您可以调整到所需的时区以获得与对象相同的时刻ZonedDateTime

ZoneId z = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdt = odt.atZoneSameInstant( z );

zdt.toString(): 2007-12-03T14:45:30+05:30[亚洲/加尔各答]

术语:“本地”</h1>

我建议您在提及调整为区域特定挂钟时间的日期时间时避免使用“本地”一词。java.time 类和其他上下文中的“本地”一词表示任何地方,而不是特定的地方。本地日期时间不是时间线上的特定时刻,只是关于一系列可能时刻的粗略概念。

例如,今年圣诞节开始的当地日期时间是2017-12-25T00:00:00,但奥克兰的午夜时刻比加尔各答早得多,在巴黎还要晚几个小时,而在蒙特利尔则更晚几个小时。

我建议您改用这些术语zoned,或者wall-clock time当您指的是通过特定时区的镜头看到的特定时刻时。

提示:偏移文字

-7这个问题在提到偏移量时碰巧使用了这些字母。我总是建议:

  • 根据 ISO 8601 的要求,使用带有填充零的两位数
  • 正如某些库和格式所期望的那样,同时使用小时和分钟。

所以使用-07:00而不是-7.

于 2017-02-15T22:54:45.067 回答