我读得越多,越感到困惑。
我对一个项目的计划是处理所有的日期/时间存储和计算在UTC除了当它涉及到显示该数据。问题是服务器将移动到不同的位置,使用不同的时区和夏令时信息,因此我必须在UI中实现某种形式的时区选择器。
但是夏令时发生的地方和不发生的地方有各种各样的例外,例如亚利桑那州没有夏令时,除了纳瓦霍印第安人保留地。所以我不能简单地使用时区位置的PHP列表(例如:"美国/凤凰城"),因为我不知道服务器的实际位置是否会在这样一个区域,所以我猜我必须实现一个复选框,说"使用夏令时"和一个更基本的选择框,简单的时区信息,例如。"CST -6"等
我可以使用'America/Phoenix'系统来显示城市列表,但这将导致一个非常长的列表。但是如果我在列表中使用EST/CST,它将不准确地显示有夏令时和没有夏令时的区域,所以我认为如果没有"DST?"复选框,我无法做到这一点。
然而,我刚刚尝试了PHP的DateTime
和DateTimeZone
与'CST', 'CDT'和'CST6CDT',所有三个结果在同一时间,无论是在二月的日期和六月的日期。我想,CDT应该与DST, CST应该没有DST, CST6CDT应该使用自动切换,但显然它不是那么简单…
所以…如果我正在使用一个时区列表,如EST/CST/PST等,并希望通过一个复选框关闭DST的能力,我该如何在PHP代码中实现?我如何告诉PHP转换时间到正确的时区与支持打开或关闭夏令时?
我知道这个的基本代码,但不知道如何改变DST:
$myTime = new DateTime('02/10/2013 08:00:00', new DateTimeZone('UTC'));
var_dump($myTime); // UTC
$localTz = new DateTimeZone('America/Phoenix'); // selected by user
$myTime->setTimezone($localTz);
var_dump($myTime); // Phoenix with local DST settings
在一个不同但相关的注意事项上,更改Linux服务器的位置是否会导致服务器的内部时钟更改时区?移动服务器会扰乱内部时钟并导致不正确的UTC时间戳吗?
作为一个花了13个月时间围绕这个问题进行重大重构的人,我可以告诉你:必须存储用户意图时间,然后将其解码为查看器本地时间。
我所说的"用户意图时间"是时间和用户所在时区的结合。随着DST的变化,您将需要使用和两个信息片段来解码要为来自不同位置的用户显示的时间。我指的不仅仅是春秋交替的时候,我指的是政府改变夏时制的法律和Olson tzdata数据库更新的时候。
你确实有一个cron作业,经常从PECL更新tzdata,对吗?:)
你会想要使用——并且很可能扩展——PHP有bug的内置DateTime和DateTimeZone。他们是你唯一的希望。
您所描述的方法以前已经使用过,并且总是存在相同的问题:
- 大多数用户不够聪明,不知道是否勾选。
- 甚至有这个方框都没有意义,因为时区规则包含了夏令时是否适用,何时适用以及适用多少的所有细节。
- 时区缩写有歧义。例如,在没有任何其他信息的情况下,你怎么知道
CST
是美国中央标准时间?它可能是指中国标准时间或古巴标准时间。这里有一个列表说明了所有的变化。 关于缩写应该是什么,人们并不总是达成一致。例如,夏威夷是HST还是HAST?
最好使用实际的IANA时区标识符,如America/Phoenix
或America/Los_Angeles
。如果您需要一种更简单的方法让您的用户选择正确的时区,请尝试基于地图的选择器,例如这个。
说明操作系统时区对PHP的影响。
-
如果你只说
new DateTime()
,那么是的-它会选择默认时区。这可以通过调用date_default_timezone_set
来更改,但是初始设置来自php.ini文件中的date.timezone
设置,或者来自操作系统的TZ
环境变量。 -
明确设置时区总是更好的,这样你就不会受到这些默认值的影响。
例如,要获取Phoenix中的当前时间:
new DateTime(null, new DateTimeZone('America/Phoenix'))
以UTC格式获取:
new DateTime(null, new DateTimeZone('UTC'))
-
您可以在有意义的地方使用UTC,但它不是强制性的。最重要的是当你保存/从数据库中检索,或者当通过api, web服务等传输时。
-
如果您总是显式的,那么服务器的时区实际上并不重要。Linux会将系统bios同步到UTC,与时区无关。Windows将同步bios与本地时间,但有一些内部,使您始终可以获得正确的UTC时间。
-
但是,将服务器设置为UTC时区仍然是"最佳实践"。这样做的主要原因是,您可以尽早发现与时区相关的代码。(最糟糕的发现时间是在你没有计划的夏时制转换的半夜。)