PHP:管理日期时间的正确方法(时间戳 Y2038 错误感知!


PHP: right way to manage DateTime (timestamp Y2038 Bug aware!)

在我的"工具箱"中,我正在使用这个函数:

function dataAttuale() {
    $now                    = new DateTime();
    $dataAttuale            = $now->format(DateTime::ISO8601);
    $offset                 = $now->getOffset();
    date_default_timezone_set('UTC');
    $nowUTC             = new DateTime();
    $dataUTC                = $nowUTC->format(DateTime::ISO8601);
    $orario             = array();
    $orario['dataAttuale']  = $dataAttuale;
    $orario['dataUTC']      = $dataUTC;
    $orario['offset']       = $offset;
    return $orario;
}

我得到这个数组

Array
(
    [dataAttuale] => 2013-10-18T11:03:52+0200
    [dataUTC] => 2013-10-18T09:03:52+0000
    [offset] => 7200
)

所以我可以在日期时间 MySql 字段中保存一个引用 UTC 的日期时间。

现在,我对此有些麻烦。

1)我也会保存偏移量(以秒为单位)。什么是最好的 Mysql 字段?我认为最大秒数可以是 +14 小时 * 60 * 60 = 50400 和 -12 小时*60*60 = -43200

2)你认为值得注意的保存也抵消吗?例如,多个 API 服务以 UTC + 偏移量返回日期...

谢谢!

更新:

谢谢两位。现在我以 UTC 格式和 varchar 时区保存 MySQL 日期时间。通过几段代码,我得到了我想要的:

$orario = new DateTime($value['creazione'], new DateTimeZone($value['timezone']));
$orario     = $orario->format(DateTime::ISO8601);

输出为(欧洲/罗马)

2013-10-19T09:27:54+0200

对于美国/蒙特利尔

2013-10-19T09:29:16-0400

澳大利亚/墨尔本

2013-10-19T09:30:31+1100

(分钟//秒的差异是在我的 PHP 脚本中更改默认时区的时间)。

现在我认为:

1)我可以嘲笑Y2038错误,放弃(叹息:()时间戳:(

2)我可以安全地环游世界并使用自己的日历(naaaa...当然,我会永远使用谷歌日历)

保存偏移量没有多大意义。您可能对时间戳有两个可能的值感兴趣:

  1. 一般全局时间戳,例如"这个世界上的时间点,即 UTC 时间 2013 年 9 月 6 日凌晨 12:52"
  2. 某个时间点的特定当地时间,例如"2012 年 12 月 19 日菲律宾马尼拉 17:34"

请注意,这两者实际上是同一件事,它们以特定位置或时区的挂钟时间和日期表示法表示时间点。唯一的区别是 UTC 是相对于其他时区偏移量表示的指定标准"位置";但菲律宾的马尼拉没有理由不能用于同样的目的。

因此,当您想要存储绝对时间戳时,您可以:

  1. 决定所有时间都存储在特定的时区(如UTC)中,并简单地存储该时间戳
  2. 确定您对特定的本地时间感兴趣并存储时间戳及其时区

无论哪种方式,您都需要时间戳,并且需要知道它位于哪个时区。在1.您事先决定所有时间戳都位于同一定义的时区中,并且不需要将其存储在 2 中。显式保存该时区信息。

偏移量不是存储的好东西,因为它全年都在变化。夏季的偏移量可能是 +6 小时到 UTC,但冬季可能是 +7。如果您稍后需要在本地化时间进行日期计算,则偏移量具有误导性,对您没有多大帮助。如果您知道您正在谈论的时区,则可以在以后的任何时间获得偏移量。

MySQL不支持DATETIME + TIMEZONE字段(例如Postgres),因此您需要将时区(例如"欧洲/柏林")存储在单独的文本字段中。如果您根本不需要将时间戳与特定位置相关联,则不需要时区,只需存储规范化的时间戳,例如规范化为 UTC。

MySQL是时区的奖励(它不存储带有日期的时区,但它将其转换为规范化格式),因此大多数时候您不需要具有偏移量的额外字段。

您只需要确保为连接设置了正确的time_zone

因此,如果您有日期并且想将其存储在数据库中,则有不同的可能性:

  1. 您可以使用SET time_zone = timezone;进行连接。你告诉MySQL你从MySQL发送或接收的日期应该在给定timezone中的方式。MySQL会在内部将其转换为规范化格式。

  2. 如果要插入具有不同时区的日期,请为time_zone设置,则可以使用CONVERT_TZ(dt,from_tz,to_tz)from_tz是日期的时区,to_tz为连接设置的时区。

在某些情况下,时区可能很重要。如果这对你的情况是真的,你的问题并不完全清楚。