Как мне сохранить дату UTC ISO8601 в базе данных MySQL? - PullRequest
21 голосов
/ 08 ноября 2011

У меня есть тысячи дат в следующем формате:

2011-10-02T23:25:42Z (он же ISO 8601 в UTC)

Какой тип данных MySQL я должен использовать для хранения такой даты ISO8601 в базе данных MySQL? Например. Datetime, timestamp или что-то еще?

Что лучше всего сравнить (например, получить записи между двумя датами / временем) и упорядочить результаты по запросам? Что делать, если база данных очень большая?

И как лучше всего преобразовать приведенную выше строку PHP для хранилища MySQL? (Я предполагаю, что date_default_timezone_set('UTC'); будет использоваться?)

Ответы [ 5 ]

15 голосов
/ 31 января 2015

Я думаю, что сохранение значений даты и времени в поле типа DATETIME было бы естественным способом.

Исходя из моего собственного опыта с моим текущим PHP-приложением, только read / write операций с этой информацией могут быть проблематичными.

Одним из возможных решений (при условии, что вы используете DATETIME тип данных) для правильного выполнения всего процесса может быть следующий подход:

Чтение значений DATETIME для использования PHP

  1. Получите DATETIME поля из вашей базы данных, преобразовав их в запросе в строковое представление в виде '2011-10-02T23:25:42Z', используя DATE_FORMAT функцию MySQL с '%Y-%m-%dT%H:%i:%sZ' форматирующей строкой ( документы на DATE_FORMAT )
  2. Считать извлеченное значение столбца в этом конкретном формате и преобразовать его в PHP из строки в реальное представление даты и времени, действительное для PHP (например, DateTime объекты класса и DateTime::createFromFormat статический метод с заданной 'Y-m-d\TH:i:s\Z' строкой форматирования (* 1029) * и Z экранированы, чтобы не рассматривать их как директивы форматирования) ( документы для метода ).
  3. Использовать преобразованные значения в качестве реальных значений даты и времени со всей применимой логикой, например, сравнения реальных дат (не сравнения текста) и т. Д.

Запись даты и времени PHP в базу данных MySQL

  1. Преобразовать то есть объект класса PHP DateTime в наш ISO 8601 в строковом представлении формата UTC, используя DateTime метод format объекта класса с таким же, как и раньше 'Y-m-d\TH:i:s\Z' форматирующей строкой ( документация ).
  2. Выполните INSERT / UPDATE операцию с информацией базы данных, используя такую ​​подготовленную строку в качестве параметра для функции MySQL STR_TO_DATE (со строкой форматирования '%Y-%m-%dT%H:%i:%sZ'), которая преобразует ее в реальное значение базы данных DATETIME () документы на STR_TO_DATE ).

Пример кода на 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
}

Этот подход очень помог мне в работе значений даты и времени между PHP и базой данных MySQL.

Надеюсь, это может оказаться полезным и для вас.

9 голосов
/ 30 января 2015

Вы можете использовать DateTime тип данных для хранения даты и времени.

Используйте функцию CAST для приведения таких строк в тип mysql DateTime.

Вот пример:

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

Это даст вам 2011-10-02 23:25:42.

Надеюсь, это поможет вам.

2 голосов
/ 05 февраля 2015

Вы не можете сохранить дату в необработанном формате 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');
1 голос
/ 03 февраля 2015

Вы можете легко преобразовать дату, используя strtotime функцию 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

Теперь вы просто вставите свою дату в MySQL, используя timestamp или datetime в зависимости от того, какойодин соответствует самым вашим потребностям.Вот самые важные вещи, которые вы должны знать об обоих типах.


Метка времени

  • Диапазон '1970-01-01 00:00:01UTC - 2038-01-09 03:14:07 UTC
  • Влияет на настройку часового пояса.
  • 4 байта памяти
  • разрешить on update current_timestamp для столбцов для всех версий.
  • Индекс намного быстрее
  • NULL не является возможным значением по умолчанию
  • Значения преобразуются из текущего часового пояса в UTC для хранения и преобразуются обратно из UTC в текущий часовой пояс для извлечения.

Datetime

  • Диапазон от 1000-01-01 00:00:00 до 9999-12-31 23: 59: 59 '
  • Константа (часовой пояс не повлияет)
  • 8-байтовое хранилище
  • разрешено обновление только для столбцов с версии 5.6.5

Что лучше всего подходит длясравнение (например, получение записей между двумя датами / временем) и упорядочение результатов по запросам?А что если база данных очень большая?

Согласно предыдущим пунктам, которые я указывал, вам следует использовать timestamp для очень большой базы данных, так как объем хранилища меньше, а индекс быстрее, чтодать вам лучшую производительность для сравнения.Однако вы ДОЛЖНЫ УБЕДИТЬСЯ ваша дата будет соответствовать ограничениям timestamp, о которых я упоминал ранее, иначе у вас нет выбора и вы должны использовать datetime.

Документацию для strtotime: http://php.net/manual/en/function.strtotime.php

И, пожалуйста, ради ответчика SO, который продолжает повторять каждый день, чтобы не использовать функции mysql* УСТАРЕЛИ , используйте PDO или mysqli*, когдаВы сделаете ваши вставки.

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

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

0 голосов
/ 08 ноября 2011

Вот пункты, почему лучше использовать datetime.

  1. С datetime вы сможете выполнять манипуляции с датами на стороне mysql - например, вычитание дня, месяца
  2. Вы сможете сортировать данные.
  3. Если база данных огромна - varchar занимает больше места на жестком диске
...