【发布时间】:2019-04-04 05:15:40
【问题描述】:
php 中的时区是这样工作的 https://www.gsp.com/support/virtual/admin/unix/tz/gmt/
当它命名为 Etc/GMT+11 时,它实际上是 GMT-11
当它命名为Etc/GMT-11 时,它实际上是GMT+11
为什么? Etc/GMT 是什么意思?
我在 PHP 中找到它,它是 PHP 中的错误还是无处不在?
【问题讨论】:
php 中的时区是这样工作的 https://www.gsp.com/support/virtual/admin/unix/tz/gmt/
当它命名为 Etc/GMT+11 时,它实际上是 GMT-11
当它命名为Etc/GMT-11 时,它实际上是GMT+11
为什么? Etc/GMT 是什么意思?
我在 PHP 中找到它,它是 PHP 中的错误还是无处不在?
【问题讨论】:
这不是错误。 Etc/GMT±* 形式的 tz 数据库标识符故意比我们在 ISO 8601 下预期的通常形式具有倒号。也就是说,它们是在 GMT 以西的正值,而不是在 GMT 以东的正值。
原因是为了向后兼容 POSIX 样式的时区标识符,例如用于the TZ environment variable 的第一种格式。当 POSIX 兼容系统解释此变量时,America/Los_Angeles 之类的值显然会落入第三种格式(在同一文档中进行了描述),但Etc/GMT+11 之类的值对于应应用哪种格式规则并不明确。因此,区域标识符必须将其符号倒置以符合要求。
From the tz database where these zones are defined:
# Be consistent with POSIX TZ settings in the Zone names, # even though this is the opposite of what many people expect. # POSIX has positive signs west of Greenwich, but many people expect # positive signs east of Greenwich. For example, TZ='Etc/GMT+4' uses # the abbreviation "-04" and corresponds to 4 hours behind UT # (i.e. west of Greenwich) even though many people would expect it to # mean 4 hours ahead of UT (i.e. east of Greenwich).
the Wikipedia article on the tz database 也对此进行了讨论。
就实际问题而言,tz 数据库评论还说:
# These entries are mostly present for historical reasons, so that # people in areas not otherwise covered by the tz files could "zic -l" # to a time zone that was right for their area. These days, the # tz files cover almost all the inhabited world, and the only practical # need now for the entries that are not on UTC are for ships at sea # that cannot use POSIX TZ settings.
因此,如果您没有为海上船只留出时间,我强烈建议您改用基于位置的标识符。 (也许是Australia/Melbourne?)
另外,更好的时区标识符来源是the one on Wikipedia。
既然您说您使用的是 PHP,请注意 the PHP documentation has a list as well,并且在 "Others" 页面上,它实际上也解释了这一点:
警告 请不要使用此处列出的任何时区(UTC 除外),它们仅出于向后兼容的原因而存在,并且可能会暴露错误行为。
警告 如果您忽略上述警告,还请注意,提供 PHP 时区支持的 IANA 时区数据库使用 POSIX 样式标志,这会导致 Etc/GMT+n 和 Etc/GMT-n 时区与常用时区相反。
例如,中国和西澳大利亚(以及其他地方)使用的比格林威治标准时间早 8 小时的时区在此数据库中实际上是 Etc/GMT-8,而不是您通常期望的 Etc/GMT+8。
再次强烈建议您使用适合您所在位置的正确时区,例如上述示例中的亚洲/上海或澳大利亚/珀斯。
【讨论】:
print_r( DateTimeZone::listIdentifiers() ); 获取“安全”时区列表