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

use*_*144 22 php mysql date iso8601 date-format

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

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

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

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

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

小智 14

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

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

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

读取DATETIME值以供PHP使用

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

将PHP日期时间写入MySQL数据库

  1. DateTime使用DateTime类对象的format方法将PHP 类对象转换为ISO 8601的UTC格式字符串表示形式,与'Y-m-d\TH:i:s\Z'格式化字符串(文档)之前相同.
  2. 使用这样准备的字符串作为MySQL函数的参数(使用格式化字符串)对数据库信息执行INSERT/ UPDATE操作,该函数将其转换为实际数据库值(STR_TO_DATE上的文档).STR_TO_DATE'%Y-%m-%dT%H:%i:%sZ'DATETIME

PHP中的示例代码

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

$db = new PDO('mysql:host=localhost;dbname=my_db;charset=utf8', 'username', 'password');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

try {
    // run the query aquring 1 example row with DATETIME data 
    // converted with MySQL DATE_FORMAT function to its string representation 
    // in the chosen format (in our case: ISO 8601 / UTC)
    $stmt = $db->query("SELECT DATE_FORMAT(dt_column, '%Y-%m-%dT%H:%i:%sZ') AS formatted_dt_col"
                        ." FROM your_table LIMIT 1"); 

    if($stmt !== FALSE) {
        $row = $stmt->fetch(PDO::FETCH_ASSOC);

        // convert the acquired string representation from DB 
        // (i.e. '2011-10-02T23:25:42Z' )
        // to PHP DateTime object which has all the logic of date-time manipulation:    
        $dateTimeObject = DateTime::createFromFormat('Y-m-d\TH:i:s\Z', $row['formatted_dt_col']);

        // the following should print i.e. 2011-10-02T23:25:42Z
        echo $dateTimeObject->format('Y-m-d\TH:i:s\Z');  

        // now let's write PHP DateTime class object '$dateTimeObject' 
        // back to the database
        $stmtInsertDT = $db->prepare("INSERT INTO your_table(dt_column) " 
                             . " VALUES ( STR_TO_DATE(:par_formatted_dt_column, '%Y-%m-%dT%H:%i:%sZ') )");

        $dtAsTextForInsert = $dateTimeObject->format('Y-m-d\TH:i:s\Z');

        // convert '$dateTimeObject' to its ISO 8601 / UTC text represantation
        // in order to be able to put in in the query using PDO text parameter
        $stmtInsertDT->bindParam(':par_formatted_dt_column', $dtAsTextForInsert, PDO::PARAM_STR);

        $stmtInsertDT->execute();

        // So the real insert query being perform would be i.e.:
        /*
           INSERT INTO your_table(dt_column) 
           VALUES ( STR_TO_DATE('2011-10-02T23:25:42Z', '%Y-%m-%dT%H:%i:%sZ') )
        */
    }
}
catch(\PDOException $pexc) {
 // serve PDOException
}
catch(\Exception $exc) {
// in case of no-PDOException, serve general exception
}
Run Code Online (Sandbox Code Playgroud)

这种方法帮助我在PHP和MySQL数据库之间操作日期时间值.

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

  • Ashish使用CAST的解决方案似乎是更好/更简单的转换方式. (2认同)

Ash*_*thi 9

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

使用CAST函数将这些字符串转换为mysql DateTime类型.

这是一个例子:

CAST("2011-10-02T23:25:42Z" AS DATETIME)
Run Code Online (Sandbox Code Playgroud)

这会给你2011-10-02 23:25:42.

希望这会帮助你.

  • 插入 `CAST('2020-01-08T06:28:43Z' AS DATETIME),` 会给我一个错误 `#1292 - 截断不正确的日期时间值:'2020-01-08T06:28:43Z'` (3认同)

小智 0

以下是为什么最好使用日期时间的要点。

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

  • @user967144 列 tz 应该是“datetime”类型,并且您传递的插入值应该使用 php `date('Ymd H:i:s',strtotime('2011-10-02T23:25:42Z')) 进行转换`..希望这有帮助 (6认同)
  • @user967144 请注意,日期末尾的字母“Z”将使 PHP 将时间转换为服务器的时区。如果您想存储 GMT 时间,则必须从日期末尾删除“Z”日期... (3认同)