我发现程序中的一个bug是由mysql的unix\u timestamp()函数在给定相同的输入时向php的strotime()返回不同的值引起的。
然后我发现错误发生的日期恰好是我所在时区夏时制生效的日期。
所以我需要知道为什么php知道夏时制开始日,而mysql不知道。php和mysql不都应该从操作系统获取时区和夏时制信息吗?
操作系统是Windows7,根据WindowsUpdate程序,它是最新的补丁。
这是我的密码:
// Checking timezones in MySQL and PHP.
echo "<pre>\n";
echo "date_default_timezone_get(): " . date_default_timezone_get() . "\n";
echo "date('P'): " . date('P') . "\n";
echo "MySQL timezone: " . $sqlObj->fetchField('SELECT IF(@@session.time_zone="SYSTEM", @@system_time_zone, @@session.time_zone)') . "\n";
// Testing MySQL and PHP conversion to unix timestamp for specific datetime values.
for ($hour = 0; $hour < 5; ++$hour)
{
$timeString = '2018-10-07 ' . (($hour < 10)? '0': '') . "$hour:00:00";
$timestampFromMySql = $sqlObj->fetchField('SELECT UNIX_TIMESTAMP(?)', array($timeString));
$timestampFromPhp = strtotime($timeString);
echo " * timestring : $timeString\n";
echo " timestampFromMySql: $timestampFromMySql\n";
echo " timestampFromPhp : $timestampFromPhp\n";
// Checking daylight savings status for the date in question in PHP.
echo " date('I', \$timestampFromMySql): " . date('I', $timestampFromMySql) . "\n";
echo " date('I', \$timestampFromPhp ): " . date('I', $timestampFromPhp ) . "\n";
echo " difference: " . ($timestampFromMySql - $timestampFromPhp) . "\n";
}
echo "</pre>\n";
这是输出。请注意,php和mysql在凌晨3点报告的unix时间中出现3600秒或1小时的差异。
date_default_timezone_get(): Australia/Melbourne
date('P'): +10:00
MySQL timezone: +10:00
* timestring : 2018-10-07 00:00:00
timestampFromMySql: 1538834400
timestampFromPhp : 1538834400
date('I', $timestampFromMySql): 0
date('I', $timestampFromPhp ): 0
difference: 0
* timestring : 2018-10-07 01:00:00
timestampFromMySql: 1538838000
timestampFromPhp : 1538838000
date('I', $timestampFromMySql): 0
date('I', $timestampFromPhp ): 0
difference: 0
* timestring : 2018-10-07 02:00:00
timestampFromMySql: 1538841600
timestampFromPhp : 1538841600
date('I', $timestampFromMySql): 1
date('I', $timestampFromPhp ): 1
difference: 0
* timestring : 2018-10-07 03:00:00
timestampFromMySql: 1538845200
timestampFromPhp : 1538841600
date('I', $timestampFromMySql): 1
date('I', $timestampFromPhp ): 1
difference: 3600
* timestring : 2018-10-07 04:00:00
timestampFromMySql: 1538848800
timestampFromPhp : 1538845200
date('I', $timestampFromMySql): 1
date('I', $timestampFromPhp ): 1
difference: 3600
谷歌告诉我,墨尔本2018年夏令时将于10月7日(星期日)凌晨2点开始,时钟将提前一小时。因此,2018年10月7日的凌晨2点实际上与2018年10月7日的凌晨3点是同一时间,因此我在上面的脚本输出中从php观察到的行为是意料之中的。mysql的行为似乎不正确。
有人能告诉我如何确保mysql拥有与夏时制相关的最新信息吗?
我还发现mysql.time\u zone表都是空的。这意味着mysql没有时区信息,还是意味着mysql的时区信息来自操作系统?
2条答案
按热度按时间wpcxdonn1#
相关文件如下:https://dev.mysql.com/doc/refman/5.5/en/time-zone-upgrades.html
关键的句子是:
“如果将mysql服务器的时区设置为system,则操作系统时间会影响mysql服务器使用的时间值”
和
如果在mysql中使用命名时区,请确保mysql数据库中的时区表是最新的
稍后的文档说明,如果mysql.time\u zone\u name表为空,则没有人可以使用命名时区,并且不需要更新这些表。
因此,要强制mysql使用时区和夏令时的操作系统信息,请将时区设置为“system”。
另外,如果时区设置为“system”,则不需要填写mysql.time\u zone表。
在通过运行“set time_zone=“system”将mysql时区设置为“system”之后,我重新运行了问题中的脚本,得到了以下输出,显示php和mysql的行为与预期相同。
z2acfund2#
这就是众所周知的mysql中unix\u timestamp函数的“特性”
https://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html
注意:如果使用unix\u timestamp()和from\u unixtime()在时间戳值和unix时间戳值之间进行转换,则转换是有损的,因为在两个方向上Map不是一对一的。例如,由于本地时区更改的约定,两个unix\u timestamp()可以将两个时间戳值Map到同一个unix时间戳值。from\u unixtime()将只将该值Map回一个原始时间戳值。下面是一个示例,使用cet时区中的时间戳值:
演练-仅在php中使用时间函数,mysql仅用于存储(datetime格式)