所以这是场景:
我的应用程序中有一个事务部分。它记录操作并将时间存储为UNIX时间戳(UTC)。
所以昨天我得到了£100.00的报酬,并将其以1477762205的unix时间戳记登录到数据库中,该时间戳记为UTC / GMT的星期六,2016年10月29日。
(对我来说,这是当地时间19:30)
我的应用程序(用PHP编写)使用datetime对象输出,并传入输出时区(欧洲/伦敦)。
昨天,它正确地输出了当地时间19:30,并且由于今天凌晨2点改变了时钟,所以现在显示为18:30。
从技术上讲,这是正确的,但是如果我记得当初记录该事务时相对于该事件,现在这似乎是不正确的,因为我记得它是本地时间19:30。
我的问题是,相对于事件,从UTC输出时间的最佳方法是什么?我需要将时区与UTC日志一起存储以确定日志发生时的时区吗?
代码:
存储日志时:
(这是我正在创建的记录器类的一部分)
if($dateTime == null) {
$dateTime = time();
}
$query = "INSERT INTO `".$this->databaseName."`.`log`(`datetime`,`action`) VALUES(?, ?);";
if(!$stmt = $this->database->prepare($query)) {
return $this->database->error;
}
$stmt->bind_param('ss',$dateTime,$action);
$stmt->execute();
输出时:
$dateTime = new DateTime(null, new DateTimeZone('UTC'));
$dateTime->setTimestamp($log->timeStamp);
$dateTime->setTimezone(new DateTimeZone('Europe/London'));
echo $dateTime->format('d/m/Y H:i');
技术上正确的输出:2016/10/29 18:30
但我希望它显示相对于实际时间戳的DST意识,而不是相对于现在的DST。
所以我希望它能输出:29/10/2016 19:30
首先,让我们总结一下1477762205
Unix时间戳的预期本地值:
只要您使用基于城市的时区标识符,东西就可以正常工作:
foreach (['UTC', 'Europe/London', 'Europe/Madrid'] as $time_zone_id) {
$dt = new DateTime('@1477762205');
$tz = new DateTimeZone($time_zone_id);
$dt->setTimezone($tz);
echo $time_zone_id . ': ' . $dt->format('H:i:s [e=T, O]') . PHP_EOL;
}
UTC: 17:30:05 [UTC=UTC, +0000]
Europe/London: 18:30:05 [Europe/London=BST, +0100]
Europe/Madrid: 19:30:05 [Europe/Madrid=CEST, +0200]
一旦使用命名区域首字母缩写词,就会发生奇怪的事情:
foreach (['UTC', 'BST', 'GMT', 'CEST', 'CET'] as $time_zone_id) {
$dt = new DateTime('@1477762205');
$tz = new DateTimeZone($time_zone_id);
$dt->setTimezone($tz);
echo $time_zone_id . ': ' . $dt->format('H:i:s [e=T, O]') . PHP_EOL;
}
UTC: 17:30:05 [UTC=UTC, +0000]
BST: 17:30:05 [BST=BST, +0000]
GMT: 17:30:05 [GMT=GMT, +0000]
CEST: 18:30:05 [CEST=CEST, +0100]
CET: 18:30:05 [CET=CET, +0100]
与基础数据库中可用的时区转换的信息(或缺乏信息)可能存在某种关系:
$dt = new DateTime('@1477762205');
foreach (['UTC', 'BST', 'Europe/London', 'CEST', 'Europe/Madrid'] as $time_zone_id) {
$tz = new DateTimeZone($time_zone_id);
$dt->setTimezone($tz);
echo $time_zone_id . PHP_EOL;
echo '- Time zone offset: ' . $tz->getOffset($dt) . ' seconds' . PHP_EOL;
$transitions = $tz->getTransitions(mktime(0, 0, 0, 1, 1, 2016), mktime(0, 0, 0, 12, 31, 2016));
if ($transitions===false) {
echo '- Error fetching transitions' . PHP_EOL;
} else {
echo '- ' . count($transitions) . ' transitions found' . PHP_EOL;
}
}
UTC
- Time zone offset: 0 seconds
- 1 transitions found
BST
- Time zone offset: 0 seconds
- Error fetching transitions
Europe/London
- Time zone offset: 3600 seconds
- 3 transitions found
CEST
- Time zone offset: 3600 seconds
- Error fetching transitions
Europe/Madrid
- Time zone offset: 7200 seconds
- 3 transitions found
很难说其中有多少是普通错误,有多少是违反直觉的,但有据可查。PHP错误数据库中挤满的不是错误条目,这的确是一种误解,但我个人发现,在涉及DST边界的日期计算中,出现了奇怪但实际的错误。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句