У меня есть тысячи дат в следующем формате:
2011-10-02T23:25:42Z
(также ISO 8601 в UTC)
Какой тип данных MySQL следует использовать для хранения такой даты ISO8601 в базе данных MySQL? Например, Datetime
, timestamp
или что-то еще?
Что лучше для сравнения (например, получение записей между двумя датами / временем) и упорядочение результатов запросов? Что, если база данных очень велика?
И какой был бы лучший способ конвертировать приведенную выше строку PHP для хранения MySQL? (Я предполагаю date_default_timezone_set('UTC');
будет использоваться?)
Я считаю, что сохранение значений даты и времени в поле типа DATETIME
было бы естественным путем.
Из моего собственного опыта с моим текущим приложением PHP, только операции read
/ write
касающиеся этой информации, могут быть проблематичными.
Одним из возможных решений (при условии, что вы используете тип данных DATETIME
) для правильного выполнения всего процесса может быть следующий подход:
DATETIME
из вашей базы данных, преобразуя их в запрос в строковое представление в виде '2011-10-02T23:25:42Z'
, используя функцию DATE_FORMAT
MySQL с '%Y-%m-%dT%H:%i:%sZ'
форматирования '%Y-%m-%dT%H:%i:%sZ'
( документы DATE_FORMAT ) DateTime::createFromFormat
и DateTime::createFromFormat
статический метод, заданный 'Ymd\TH:i:s\Z'
форматирование строка ( T
и Z
экранированы, чтобы избежать обработки их как директив форматирования) ( docs для метода ). DateTime
в наш ISO 8601 в 'Ymd\TH:i:s\Z'
представлении формата UTC с использованием метода format
объекта DateTime
с тем же значением, что и перед 'Ymd\TH:i:s\Z'
( документация ). INSERT
/ UPDATE
в базе данных с использованием такой подготовленной строки в качестве параметра для функции MySQL STR_TO_DATE
(с STR_TO_DATE
'%Y-%m-%dT%H:%i:%sZ'
), которая преобразует ее в реальную базу данных. Значение DATETIME
( документы на STR_TO_DATE ). Ниже приведен пример примера такого подхода с использованием объектов 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 // (ie '2011-10-02T23:25:42Z' ) // to PHP DateTime object which has all the logic of date-time manipulation: $dateTimeObject = DateTime::createFromFormat('Ymd\TH:i:s\Z', $row['formatted_dt_col']); // the following should print ie 2011-10-02T23:25:42Z echo $dateTimeObject->format('Ymd\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('Ymd\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 ie: /* 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.
Надеюсь, это тоже поможет вам.
Вы можете использовать тип данных DateTime
для хранения даты и времени.
Используйте функцию CAST
для перевода таких строк в тип mysql DateTime
.
Вот пример:
CAST("2011-10-02T23:25:42Z" AS DATETIME)
Это даст вам 2011-10-02 23:25:42
.
Надеюсь, что это поможет вам.
Вы можете легко преобразовать дату, используя функцию 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\tg:ia', $time); //convert to date if you prefer, credit to Marc B for the parameters
Теперь вы просто вставляете свою дату в MySQL
используя timestamp
или datetime
зависимости от того, какой из них наиболее подходит вашим потребностям. Здесь самые важные вещи, которые вы должны знать об обоих типах.
Отметка
on update current_timestamp
по столбцам для всех версий. NULL
не является возможным значением по умолчанию UTC
для хранения и преобразуются обратно из UTC
в текущую временную зону для извлечения. Datetime
5.6.5
Что лучше для сравнения (например, получение записей между двумя датами / временем) и упорядочение результатов запросов? Что, если база данных очень велика?
В соответствии с предыдущими пунктами, которые я изложил, вы должны использовать timestamp
для очень большой базы данных, поскольку хранилище меньше, а индекс быстрее, что даст вам лучшую производительность для сравнения. Тем не менее, вы ДОЛЖНЫ УДОВЛЕТВОРИТЬ, что ваша дата будет соответствовать ограничениям timestamp
я упоминал ранее, иначе у вас нет выбора и вы должны использовать datetime
.
Документация для strtotime
: http://php.net/manual/en/function.strtotime.php
И, пожалуйста, ради ответчика SO, который каждый день повторяет, чтобы не использовать функции mysql*
DEPRECATED , используйте PDO
или mysqli*
когда вы будете делать свои вставки.
Вы не можете хранить дату в необработанном формате 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/ru/time-zone-support.html
Итак, если вы выполняете в PHP
date_default_timezone_set('UTC');
и в MySQL
SET time_zone = +00:00
Конечно, PHP и MySQL будут использовать UTC.
После этого вы можете преобразовать все строки базы данных в DateTime, не заботясь о несоответствии часового пояса.
Чтобы преобразовать любой PHP DateTime (без учета внутреннего часового пояса) в строку MySQL datetime, вы должны установить часовой пояс объекта DateTime в UTC.
$datetime->setTimezone(new DateTimeZone('UTC'))->format('Ymd H:i:s');
Вот моменты, по которым лучше использовать datetime.