事件相对时间

丹色DJ1

所以这是场景:

我的应用程序中有一个事务部分。它记录操作并将时间存储为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

阿尔瓦罗·冈萨雷斯(Alvaro Gonzalez)

首先,让我们总结一下1477762205Unix时间戳的预期本地值

  • UTC:173005(UTC,+ 0000)
  • 伦敦:183005(BST,+ 0100 aka 3600,DST = 1)
  • 马德里:19 : 30 : 05(CEST,+ 0200 aka 7200,DST = 1)

只要您使用基于城市的时区标识符,东西就可以正常工作:

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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章