mysql php 时区一致性_PHP,MySQL和时区

这个答案已经更新,以适应赏金。未经编辑的原始答案在线下。

在时区的背景下,赏金所有者添加的几乎所有问题点都与MySQL和PHP日期时间应该如何交互有关。

>将MySQL连接时区设置为UTC,如上面的链接中所述。这将导致MySQL处理的所有日期时间(包括NOW())得到妥善处理。

> Always use DATETIME, never use TIMESTAMP除非您非常明确地要求TIMESTAMP中的特殊行为。这比过去痛苦少。

>如果必须,可以将Unix纪元时间存储为整数,例如用于传统目的。时代是UTC。

> MySQL的首选日期时间格式是使用PHP日期格式字符串Y-m-d H:i:s创建的

>将所有PHP日期时间转换为UTC,将其存储在MySQL中,这是一个简单的事情,如下所述

>从MySQL返回的日期时间可以安全地传递给PHP DateTime构造函数。一定要传入UTC时区!

>在回声时将PHP DateTime转换为用户的本地时区。值得庆幸的是DateTime比较和数字与其他DateTimes将考虑每个DateTimes的时区。

>您仍然可以使用PHP提供的DST数据库。让您的PHP和OS补丁保持最新!让MySQL处于幸福的UTC状态,以消除一个潜在的DST烦恼。

这解决了大多数问题。

最后一件事是doozy:

What should someone do if they have previously inserted data (e.g. using NOW()) without worrying about the time zone to make sure everything stays consistent?

这是一个真正的烦恼。其中一个答案指出MySQL的CONVERT_TZ,虽然我个人已经通过在选择和更新期间在服务器本地和UTC时区之间跳跃来做到这一点,因为我是那样的硬核。

the app should also be able to SET/Choose the DST accordingly itself for each user.

在现代,你不需要也不应该这样做。

现代版本的PHP具有DateTimeZone类,其中包括list named timezones的功能。命名时区允许用户选择其实际位置,并让系统根据该位置自动确定其DST规则。

您可以将DateTimeZone与DateTime结合使用,以实现一些简单但功能强大的功能。您可以在UTC by default中简单地存储和使用所有时间戳,并将它们转换为显示的用户时区。

// UTC default

date_default_timezone_set('UTC');

// Note the lack of time zone specified with this timestamp.

$nowish = new DateTime('2011-04-23 21:44:00');

echo $nowish->format('Y-m-d H:i:s'); // 2011-04-23 21:44:00

// Let's pretend we're on the US west coast.

// This will be PDT right now, UTC-7

$la = new DateTimeZone('America/Los_Angeles');

// Update the DateTime's timezone...

$nowish->setTimeZone($la);

// and show the result

echo $nowish->format('Y-m-d H:i:s'); // 2011-04-23 14:44:00

通过使用此技术,系统将自动为用户选择正确的DST设置,而无需询问用户他们当前是否在DST中。

您可以使用类似的方法渲染选择菜单。您可以不断为单个DateTime对象重新分配时区。例如,此代码将列出区域及其当前时间,此时:

$dt = new DateTime('now', new DateTimeZone('UTC'));

foreach(DateTimeZone::listIdentifiers() as $tz) {

$dt->setTimeZone(new DateTimeZone($tz));

echo $tz, ': ', $dt->format('Y-m-d H:i:s'), "\n";

}

您可以通过使用一些客户端魔术来大大简化选择过程。 Javascript有一个spotty but functional Date类,标准方法为get the UTC offset in minutes.你可以使用它来帮助缩小可能的时区列表,盲目假设用户的时钟是正确的。

让我们自己比较一下这种方法。除了向用户推断他们不会真正关心的选择之外,您每次操作日期时都需要实际执行日期数学运算。这不仅仅是次优的,它是蝙蝠 – 鸟粪疯狂。强制用户表示他们何时需要DST支持,这就是要求麻烦和困惑。

此外,如果您想使用现代PHP DateTime和DateTimeZone框架,则需要使用use deprecated Etc/GMT... timezone strings而不是命名时区。这些区域名称可能会从未来的PHP版本中删除,因此这样做是不明智的。我从经验中说出这一切。

tl; dr:使用现代工具集,免除日期数学的恐怖。向用户显示指定时区列表。以UTC格式存储您的日期,这不会受到DST的任何影响。将日期时间转换为显示的用户所选的指定时区,而不是更早。

根据要求,这里是可用时区的循环,以分钟为单位显示其GMT偏移。我在这里选择了几分钟来证明一个不幸的事实:并非所有的补偿都在整个小时内!有些人实际上在DST期间提前半小时而不是整整一小时。以分钟为单位的结果偏移量应与Javascript的Date.getTimezoneOffset匹配。

$utc = new DateTimeZone('UTC');

$dt = new DateTime('now', $utc);

foreach(DateTimeZone::listIdentifiers() as $tz) {

$local = new DateTimeZone($tz);

$dt->setTimeZone($local);

$offset = $local->getOffset($dt); // Yeah, really.

echo $tz, ': ',

$dt->format('Y-m-d H:i:s'),

', offset = ',

($offset / 60),

" minutes\n";

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值