如何在UTC数据库中存储UTCISO8601日期?

时间:2011-11-08 08:01:24

标签: php mysql date date-format iso8601

我有以下格式的数千个日期:

2011-10-02T23:25:42Z(又名ISO 8601,UTC)

我应该使用什么MySQL数据类型在MySQL数据库中存储这样的ISO8601日期?例如。 Datetimetimestamp或其他什么?

哪个最适合比较(例如,在两个日期/时间之间获取记录)并从查询中排序结果?如果数据库非常大呢?

将上述PHP字符串转换为MySQL存储的最佳方法是什么? (我猜是会使用date_default_timezone_set('UTC');?)

6 个答案:

答案 0 :(得分:15)

我认为将日期时间值保存在DATETIME类型的字段中将是一种自然的方式。

根据我自己对当前PHP应用程序的使用经验,只有read / write有关此信息的操作可能会有问题。

可能的解决方案之一(假设您使用DATETIME数据类型)来正确执行整个过程可能是以下方法:

读取PHP使用的DATETIME值

  1. 从数据库中获取DATETIME字段,使用'2011-10-02T23:25:42Z' MySQL函数DATE_FORMAT将{<1}}形式的字符串表示形式转换为查询中的字符串表示形式格式化字符串( docs on DATE_FORMAT
  2. 以此特定格式读取已获取的列值,并将其在PHP中从字符串转换为对PHP有效的实际日期时间表示(例如'%Y-%m-%dT%H:%i:%sZ'类对象和DateTime静态方法{{1}格式化字符串(DateTime::createFromFormat'Y-m-d\TH:i:s\Z'被转义以避免将它们视为格式化指令)( docs for the method )。
  3. 将转换后的值用作所有适用逻辑的实际日期时间值,例如实际日期比较(不是文本比较)等。
  4. 将PHP日期时间写入MySQL数据库

    1. 使用T类对象的Z方法将PHP DateTime类对象转换为ISO 8601的UTC格式字符串表示,其方法与之前DateTime相同格式化字符串( documentation )。
    2. 使用此类准备好的字符串作为MySQL函数format(带'Y-m-d\TH:i:s\Z'格式化字符串)的参数,对数据库信息执行INSERT / UPDATE操作,将其转换为真实数据库STR_TO_DATE值( docs on STR_TO_DATE )。
    3. PHP中的示例代码

      请在下面找到使用PDO对象的此类方法的草案示例:

      '%Y-%m-%dT%H:%i:%sZ'

      这种方法帮助我在PHP和MySQL数据库之间运行日期时间值。

      我希望它也可能对你有所帮助。

答案 1 :(得分:9)

您可以使用DateTime数据类型来存储日期和时间。

使用CAST函数将此类字符串强制转换为mysql DateTime类型。

以下是一个例子:

CAST("2011-10-02T23:25:42Z" AS DATETIME)

这将为您提供2011-10-02 23:25:42

希望这会对你有所帮助。

答案 2 :(得分:2)

您不能以原始UTC ISO8601格式存储日期(使用2011-10-02T23:25:42Z表示)并保存所有SQL DATETIME功能。

但是你应该知道,MySQL(关于http://dev.mysql.com/doc/refman/5.5/en/datetime.html)总是以UTC格式存储时间/日期。 您还可以修改连接的时区 http://dev.mysql.com/doc/refman/5.5/en/time-zone-support.html

所以,如果你在PHP中执行

date_default_timezone_set('UTC');

和MySQL

SET time_zone = +00:00

确保PHP和MySQL使用UTC。

之后,您可以将所有数据库字符串转换为DateTime,而无需关心时区不匹配。

要将任何PHP DateTime(不带有其内部时区)转换为MySQL日期时间字符串,您应将DateTime对象时区设置为UTC。

$datetime->setTimezone(new DateTimeZone('UTC'))->format('Y-m-d H:i:s');

答案 3 :(得分:1)

您可以使用strtotime的{​​{1}}函数轻松转换日期:

php

现在,您只需使用date_default_timezone_set('UTC'); $date = '2011-10-02T23:25:42Z';//(aka ISO 8601 in UTC) $time = strtotime($date); //time is now equals to the timestamp $converted = date('l, F jS Y \a\t g:ia', $time); //convert to date if you prefer, credit to Marc B for the parameters MySQLtimestamp中插入日期,具体取决于您最需要的日期。这里有关于这两种类型的最重要的事情。


<强>时间戳

  • “1970-01-01 00:00:01”UTC到“2038-01-09 03:14:07”UTC的范围
  • 受时区设置的影响。
  • 4字节存储
  • 允许所有版本的列datetime
  • 索引更快
  • on update current_timestamp不是可能的默认值
  • 将值从当前时区转换为NULL进行存储,并从UTC转换回当前时区进行检索。

<强>日期时间

  • '1000-01-01 00:00:00'至'9999-12-31 23:59:59'
  • 的范围
  • 常数(时区不会影响)
  • 8字节存储
  • 仅允许在版本UTC
  • 时更新列
  

最适合比较(例如,获取两者之间的记录)   日期/时间)并从查询中排序结果?怎么样的呢   数据库非常大?

根据我之前提到的观点,那么你应该使用5.6.5作为一个非常大的数据库,因为存储空间较小,而且索引更快,这将为你提供更好的比较性能。但是,您必须确定您的日期将符合我之前提到的timestamp的限制,否则您别无选择,必须使用timestamp

datetime的文档:http://php.net/manual/en/function.strtotime.php

并且,为了SO的回答者每天不断重复使用strtotime 已弃用的功能,请使用mysql*PDO时你会做插页。

http://php.net/manual/en/book.pdo.php

http://php.net/manual/en/book.mysqli.php

答案 4 :(得分:1)

在我的系统上使用您的日期时间PDT:

SELECT CONVERT_TZ(str_to_date('2011-10-02T23:25:42Z','%Y-%m-%dT%H:%i:%sZ'),'+00:00','SYSTEM') from dual;

2011-10-02 16:25:42

如果您的日期时间以分数微秒为单位;在Z之前添加。%f,如下所示:

SELECT CONVERT_TZ(str_to_date('2011-10-02T23:25:42.123456Z','%Y-%m-%dT%H:%i:%s.%fZ'),'+00:00','SYSTEM') from dual;

2011-10-02 16:25:42.123456

答案 5 :(得分:0)

以下是使用日期时间更好的原因。

  1. 使用datetime,您可以在mysql端进行日期操作 - 例如减去日,月
  2. 您将能够对数据进行排序。
  3. 如果DB很大 - varchar在HDD上占据更多位置