据我所知,如果时区偏离GMT(例如太平洋夏令时间为-7小时),则向用户显示本地时间非常容易。
但是,如果我想继续在很长一段时间内(例如1年)继续显示正确的当地时间,该怎么办?鉴于GMT的偏差,您不知道用户所在的时区。例如。给定-7,用户可以居住在美国或加拿大(或其他一些国家)。这些国家我在一年中的不同时间点有不同的当地时间(例如,如果美国改为3月的白天时间和4月的CA)。
我的问题是,上段是否正确?是否有一种标准的方法来获取GMT偏移量并对用户所在的时区做出很好的猜测?
答案 0 :(得分:1)
您的结论是正确的:没有可靠的方法来识别time zone中的offset-from-UTC。
对于-07:00
的偏移量示例,我在the current list中计算了三十个可能的时区,包括:America/Boise
,America/Chihuahua
,和America/Edmonton
。
时区实际上是偏移的集合 ,记录随着时间的推移所做的更改,在该区域内使用某段偏移一段时间但随后又被更改另一段时间。
例如,在每年的America/Los_Angeles
部分中,-08:00
的偏移量为-07:00
,而一年中的另一部分则为America/Phoenix
。因此,该时区正在累积每年至少两个偏移的历史。相比之下,使用时区-07:00
的邻近区域不累积其偏移量的变化,几十年来保持相同的2007-12-03T10:15:30+01:00
偏移量。
因此,我们在偏移和时区之间存在多对多的关系。偏移可能出现在一个或多个时区中。并且每个时区可以有一个或多个偏移(已经改变历史记录)。
这就是为什么java.time类ZonedDateTime
的设计者冒昧地使用toString
方法扩展标准ISO 8601格式,仅使用偏移量来附加名称方括号中的时区。
例如,该类不是简单地生成标准格式2007-12-03T10:15:30+01:00[Europe/Paris]
,而是生成ZonedDateTime.now( ZoneId.of( "America/Montreal" ) )
.toString()
,其中附加了区域Europe/Paris的名称。
Instant
2007-12-03T10:15:30 + 01:00 [欧洲/巴黎]
我希望这种附加时区名称的做法能够抓住。缺乏时区名称是标准委员会的一个令人惊讶的遗漏,否则他们在设计ISO 8601方面表现出色。
您可以使用业务场景环境中的线索猜测有关时区的信息。但我建议反对。猜测是有风险的,特别是因为世界各地的政治家都喜欢经常重新定义时区。
存储,序列化和交换日期时间值的最佳做法通常是调整为UTC。假设日期时间库的tzdata是最新的,则调整为UTC会提供始终正确且明确的可靠值。
例如,在Java中,这意味着使用或提取Instant instant = Instant.now();
对象。 Instant
类代表UTC中时间轴上的一个时刻,分辨率为nanoseconds(小数部分最多九(9)位)。
ZonedDateTime zdt = ZonedDateTime.now( ZoneId.of( "America/Montreal" ) );
Instant instant = zdt.toInstant();
...或...
Z
表示此类值的标准ISO 8601格式字符串使用Zulu
作为OffsetDateTime
的缩写,表示UTC。
2007-12-03T09:15:30Z
OffsetDateTime odt = OffsetDateTime.parse( "2007-12-03T10:15:30+01:00" );
如果给出一个表示只有偏移的日期时间的字符串,则将其解析为OffsetDateTime
对象。
Instant
odt.toString():2007-12-03T10:15:30 + 01:00
从那里你可以用UTC提取一个值Instant instant = odt.toInstant();
。
ZoneId z = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdt = odt.atZoneSameInstant( z );
instant.toString():2007-12-03T09:15:30Z
或者您可以调整到所需的时区,以获得与ZonedDateTime
对象相同的时刻。
2017-12-25T00:00:00
zdt.toString():2007-12-03T14:45:30 + 05:30 [亚洲/加尔各答]
我建议您在将日期时间调整为某个地区的特定wall-clock time时避免使用“本地”一词。 java.time类和其他上下文中的“local”一词表示任何位置,而不是特定的位置。本地日期时间不时间轴上的特定时刻,只是对一系列可能时刻的粗略概念。
例如,今年圣诞节开始时的当地日期时间为zoned
,但奥克兰的午夜时间比加尔各答要早得多,而且几个小时后在巴黎也是如此,甚至更长时间之后在蒙特利尔。
我建议您使用术语wall-clock time
或-7
,当您指的是通过特定时区镜头看到的特定时刻时。
在提到偏移量时,问题恰好使用了字母-07:00
。我总是建议:
因此请使用-7
而不是{{1}}。