Работа с датой и временем в MySQL

Вы здесь: Главная — MySQL — MySQL Основы — Работа с датой и временем в MySQL

Работа с датой и временем в MySQL

В данной статье мы поговорим о том как работать с датой и временем в MySQL. Посмотрим как сохранять и извлекать значения данного типа из таблиц.

Форматы даты и времени в MySQL

MySQL поддерживает несколько форматов даты и времени:

  • DATE — хранит значение даты в формате ГГГГ-ММ-ДД. Например 2019-03-28
  • DATETIME — хранит значение даты и времени в формате ГГГГ-ММ-ДД HH:MM:SS. Например, 2019-03-28 10:00:00. Диапазон поддерживаемых значений — от 1000-01-01 00:00:00 до 9999-12-31 23:59:59
  • TIMESTAMP — похож на DATETIME, с небольшими отличиями, зависящими от версии MySQL
    и режима в котором запущен сервер

Создание таблицы с колонками DATE и DATETIME

CREATE TABLE `orders` (
  `order_no`       INT  NOT NULL AUTO_INCREMENT,
  `order_item`     TEXT  NOT NULL,
  `order_date`     DATETIME  NOT NULL,
  `order_delivery` DATE  NOT NULL,
                   PRIMARY KEY (`order_no`)
)
ENGINE = InnoDB;

Колонка order_date имеет тип DATETIME, так как предполагается, что нам необходимо записывать точное время и дату осуществления заказа. Точное время доставки, как правило неизвестно, поэтому колонка order_delivery имеет тип DATE, необходимый для фиксации даты доставки.

Формат даты и времени может быть следующий:

2019-03-28 10:00:00
20190328100000
2019/03/28 10.00.00
2019*03*28*10*00*00

Как видите, MySQL обеспечивает широкие и гибкие возможности по форматирванию даты и времени.

В добавок к механизму хранения даты и времени, в MySQL есть большой набор функций для работы датой и временем. Далее представлены некоторые из них:

  • ADDDATE() — Суммирует даты
  • CURDATE() — Возвращает текущую дату
  • CURTIME()
    — Возвращает текущее системное время
  • DATE_FORMAT() — Форматирует дату
  • DAYNAME() — Возвращает имя дня недели
  • DAYOFMONTH() — Возвращает день месяца (1-31)
  • DAYOFYEAR() — Возвращает день года (1-366)
  • FROM_UNIXTIME() — Форматирует дату, представленную типом UNIX timestamp
  • HOUR() — Извлекает часы
  • NOW() — Возвращает текущую дату и время

Вот такие развитые средства содержит MySQL для работы с датой и временем.

  • Работа с датой и временем в MySQL Создано 28.03.2019 11:49:34
  • Работа с датой и временем в MySQL Михаил Русаков
Предыдущая статья Следующая статья

Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (http://myrusakov.ru)!

Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/rusakovmy.

Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления

Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.

Порекомендуйте эту статью друзьям:

Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):

  1. Кнопка:
    <a href=»https://myrusakov.ru» target=»_blank»><img src=»https://myrusakov.ru/images/button.gif» alt=»Как создать свой сайт» /></a>

    Она выглядит вот так: Как создать свой сайт

  2. Текстовая ссылка:
    <a href=»https://myrusakov.ru» target=»_blank»>Как создать свой сайт</a>

    Она выглядит вот так: Как создать свой сайт

  3. BB-код ссылки для форумов (например, можете поставить её в подписи):
    [URL=»https://myrusakov.ru»]Как создать свой сайт[/URL]

myrusakov.ru

Календарные типы данных в MySQL: особенности использования / Habr

В MySQL 5 есть несколько типов данных для хранения даты и времени. Это TIMESTAMP, DATE, DATETIME, TIME и YEAR. Все они обладают своими особенностями, и выбор в пользу того или иного календарного типа должен производиться отдельно в каждой конкретной ситуации. Я хотел бы поделиться с вами результатом моего сегодняшнего миниисследования этих типов, в том числе в аспекте работы с временными зонами.

Итак, все календарные типы данных подробно описаны в разделе «10.3. Date and Time Types» руководства по MySQL. А важная информация, касающаяся поддержки СУБД временных зон, расписана в разделе «9.7. MySQL Server Time Zone Support». Все следующее далее базируется на изучении руководства. В то же время, в здесь указаны лишь нюансы выбора в пользу того или иного типа, поэтому этот материал никак не заменяет мануал, но дополняет его.

Вначале краткая характеристика каждого из типов:

  • TIMESTAMP — тип данных для хранения даты и времени. Данные хранятся в виде количества секунд, прошедших с начала «эпохи Юникса». Диапазон значений: 1970-01-01 00:00:00 — 2038-12-31 00:00:00. Занимает 4 байта.
  • YEAR — тип данных для хранения года. Диапазон значений: 1901 — 2155. Занимает 1 байт.
  • DATE — тип данных для хранения даты. Диапазон значений: 1000-01-01 — 9999-12-31. Занимает 3 байта.
  • TIME — тип данных для хранения времени. Диапазон значений: −828:59:59 — 828:59:59. Занимает 3 байта.
  • DATETIME — тип данных для хранения даты и времени. Диапазон значений: 1000-01-01 00:00:00 — 9999-12-31 00:00:00. Занимает 8 байт.

Хозяйке на заметку. Интересно то, что большинство программистов полагают, что понятие «timestamp» — это и есть Unix-время. На самом же деле, timestamp — это метка, которая представляет собой последовательность символов, обозначающих дату и / или время, когда определенное событие произошло. А «время Юникса» (Unix time) или POSIX time — это количество секунд, прошедших с полуночи 1 января 1970 года по UTC. Понятие timestamp шире, чем Unix time.

Проанализировав описание типов, представленное выше, можно сделать практически все выводы о достоинствах и недостатках тех или иных типов. Все довольно просто и очевидно.

Но прежде, чем рассказать об использовании этих типов, хочу заметить, что на практике часто используется другой тип для хранения даты и времени: целочисленное значение (для хранения даты — INT (4 байта), даты и времени — BIGINT (8 байт)). Отличие использования целочисленных типов от DATE и DATETIME лишь в том, что при выводе данные не форматируются, а в вычислениях с датами и временем целые числа требуется преобразовывать в соответствующий календарный тип. Кроме того, не производится проверка на валидность представленного значения перед сохранением. Возможности сортировки сохраняются. Поэтому INT и BIGINT имеет смысл использовать в тех же случаях, как DATE и DATETIME, с целью максимизации переносимости и независимости от СУБД. Других преимуществ я не вижу, если они есть, предлагаю указать в комментах.

Использование календарных типов данный в MySQL


Начнем с самого простого — тип YEAR. Единственное его достоинство — малый размер — всего-то 1 байт. Но из-за этого действует строгое ограничение по диапазону допустимых значений (тип может хранить только 255 разных значений). Мне сложно представить практическую ситуацию, когда может потребоваться хранить года строго в диапазоне от 1901 до 2155. Кроме того, тип SMALLINT (2 байта) дает диапазон, достаточный в большинстве ситуаций для хранения года. А экономить 1 байт на строке в таблице БД в наше время смысла нет.

Типы DATE и DATETIME можно объединить в одну группу. Они хранят дату или дату и время с довольно широким диапазоном допустимых значений, независимую от установленной на сервере временной зоны. Их использование определенно имеет практический смысл. Но если требуется хранить даты исторических событий, уходящие в прошлое за Нашу эру, придется выбрать другие типы данных. Для хранения дат неких событий, потенциально выходящих за рамки диапазона типа TIMESTAMP (дни рождений, даты выпуска продуктов, избрания президентов, запуски космических ракет и т.д.), отлично подойдут эти типы. При использовании этих типов нужно учитывать один важный нюанс, но об этом ниже.

Тип TIME можно использовать для хранения промежутка времени, когда не нужна точность меньше 1 секунды, и промежутки времени меньше 829 часов. Добавить тут больше нечего.

Остался самый интересный тип — TIMESTAMP. Рассматривать его надо в сравнении с DATE и DATETIME: TIMESTAMP тоже предназначен для хранения даты и/или времени происхождения неких событий. Важное отличие между ними в диапазонах значений: очевидно, что TIMESTAMP не годится для хранения исторических событий (даже таких, как дни рождений), но отлично подходит для хранения текущих (логирование, даты размещения статей, добавления товаров, оформления заказов) и предстоящих в обозримом будущем событий (выходы новых версий, календари и планировщики и т.д).

Основное удобство использования типа TIMESTAMP состоит в том, что для столбцов этого типа в таблицах можно задавать значение по умолчанию в виде подстановки текущего времени, а так же установки текущего времени при обновлении записи. Если вам требуется эти возможности, то с вероятностью 99% TIMESTAMP — именно то, что вам нужно. (Как этоделать, смотрите в мануале.)

Не стоит бояться того, что с приближением к 2038 году ваш софт перестанет работать. Во-первых, до этого времени вашим софтом, скорее всего, просто перестанут пользоваться (особенно версиями, которые пишутся сейчас). Во-вторых, с приближением к этой дате разработчики MySQL обязательно что-нибудь придумают для сохранения работоспособности вашего софта. Все решится так же хорошо, как проблема Y2K.

Итак, тип TIMESTAMP используем для хранения дат и времени свершения событий нашего времени, а DATETIME и DATE — для хранения дат и времени свершения исторических событий, или событий глубокого будущего.

Диапазоны значений — это важное отличие между типами TIMESTAMP, DATETIME и DATE, но не главное. Главное то, что TIMESTAMP хранит значение в UTC. При сохранении значения оно переводится из текущего временной зоны в UTC, а при его чтении — во время текущей временной зоны из UTC. DATETIME и DATE хранят и выводят всегда одно и то же время, независимо от временных зон.

Временные зоны устанавливаются в СУБД MySQL глобально или для текущего подключения.Последнее можно использовать для обеспечения работы разных пользователей в разных временных зонах на уровне СУБД. Все значения времени физически будут храниться в UTC, а приниматься от клиента и отдаваться клинту — в значениях его временной зоны. Но только при использовании типа данных TIMESTAMP. DATE и DATETIME всегда принимают, хранят и отдают одно и то же значение.

Функция NOW() и ее синонимы возвращают значение времени в текущей временной зоне пользователя.

Учитывая все эти обстоятельства, необходимо быть крайне внимательными при изменении временной зоны в пределах подключения к серверу и использовании типов DATE и DATETIME. Если надо хранить дату (например, дату рождения), то никаких проблем не будет. Дата рождения в любой зоне одинаковая. Т.е. если вы родились 1 января в 0:00 UTC/GMT+0, то это не значит, что в Америке будут праздновать ваш день рождения 31 декабря. Но если вы решите хранить время события в столбце DATETIME, то тут уже построить работу с пользовательскими временными зонами на уровне СУБД просто не выйдет. Поясню на примере:

Пользователь X работает в зоне UTC/GMT+2, Y — в зоне UTC/GMT+3. Для соединений пользователей с MySQL установлена соответствующая (у каждого своя) временная зона. Пользователь размещает сообщение на форуме, нас интересует дата написания сообщения.

Вариант 1: DATETIME. Пользователь X пишет сообщение в 14:00 UTC/GMT+2. Значение в поле «дата» сообщения подставляется как результат выполнения функции NOW() — 14:00. Пользователь Y считывает время написания сообщения и видит те же 14:00. Но у него в настройках стоитзона UTC/GMT+3, и он думает, что сообщение было написано не только что, а час назад.

Вариант 2: TIMESTAMP. Пользователь X пишет сообщение в 14:00 UTC/GMT+2. В поле «дата» попадает результат выполнения функции NOW() — в данном случае — 12:00 UTC/GMT+0. ПользовательY считывает время написания сообщения и получает (UTC/GMT+3)(12:00 UTC/GMT+0) = 15:00 UTC/GMT+3. Все получается ровно так, как мы хотим. И главное — пользоваться этим крайне удобно: для поддержки пользовательских временных зон не нужно писать никакой код приведения времени.

Возможности подстановки текущего времени и работы с временными зонами в типе TIMESTAMP настолько весомы, что если вам в неком логе надо хранить дату без времени, все равно стоит использовать TIMESTAMP, вместо DATE, не экономя 1 байт разницы между ними. При этом на «00:00:00» просто не обращать внимания.

Если же вы не можете использовать TIMESTAMP из-за относительно малого диапазона его значений (а обычно это 1—2 случая против 10—15 в базе сайта), придется использовать DATETIME и аккуратно его корректировать значения в нужных местах (т.е. при записи в это поле переводить дату в UTC, а при чтении — во время в зоне считывающего пользователя). Если вы храните только дату, то скорее всего не важно, какая у вас временная зона: новый год все празднуют 1 января по локальному времени, ничего переводить тут не понадобится.

habr.com

Дата / время функции MySQL — Oracle PL/SQL •MySQL •MariaDB •SQL Server •SQLite

Функция & Описание
ADDDATE
MySQL функция ADDDATE возвращает дату, после которой добавлен определенный интервал дата/время.
ADDTIME
MySQL функция ADDTIME возвращает значение дата/время и времени, к которому был добавлен временной интервал.
CURDATE
MySQL функция CURDATE возвращает текущую дату.
CURRENT_DATE
MySQL функция CURRENT_DATE возвращает текущую дату.
CURRENT_TIME
MySQL функция CURRENT_TIME возвращает текущее время.
CURRENT_TIMESTAMP
MySQL функция CURRENT_TIMESTAMP возвращает текущую дату и время.
CURTIME
MySQL функция CURTIME возвращает текущее время.
DATE
MySQL функция DATE возвращает значение даты из даты/времени.
DATE_ADD
MySQL функция DATE_ADD возвращает дату, после которой был добавлен определенный интервал даты/времени.
DATE_FORMAT
MySQL функция DATE_FORMAT форматирует дату по заданной маске.
DATE_SUB
MySQL функция DATE_SUB возвращает дату, после которой вычитается определенный интервал даты/времени.
DATEDIFF
MySQL функция DATEDIFF возвращает разность дней между двумя значениями даты.
DAY
MySQL функция DAY возвращает номер дня месяца из даты.
DAYNAME
MySQL функция DAYNAME возвращает название дня недели (англ.) из даты.
DAYOFMONTH
MySQL функция DAYOFMONTH возвращает номер дня месяца из даты.
DAYOFWEEK
MySQL функция DAYOFWEEK возвращает номер дня недели для значения даты. Необходимо помнить, что в западных странах неделя начинается с воскресения, суббота соответственно последний день недели.
DAYOFYEAR
MySQL функция DAYOFYEAR возвращает день года из определенной даты.
EXTRACT
MySQL функция EXTRACT извлекает детали из даты.
FROM_DAYS
MySQL функция FROM_DAYS принимает числовое значение дня по которому возвращает значение даты.
HOUR
MySQL функция HOUR возвращает часы из значения даты.
LAST_DAY
MySQL функция LAST_DAY возвращает последний день месяца для определенной даты.
LOCALTIME
MySQL функция LOCALTIME возвращает текущую дату и время.
LOCALTIMESTAMP
MySQL функция LOCALTIMESTAMP возвращает текущую дату и время.
MAKEDATE
MySQL функция MAKEDATE возвращает дату для определенного значения года и дня года.
MAKETIME
MySQL функция MAKETIME возвращает время для определенной комбинации часов, минут и секунд.
MICROSECOND
MySQL функция MICROSECOND возвращает микросекундную часть значения даты.
MINUTE
MySQL функция MINUTE возвращает минуты из значения даты.
MONTH
MySQL функция MONTH возвращает числовое значение месяца из даты.
MONTHNAME
MySQL функция MONTHNAME возвращает полное название месяца (англ.) из даты.
NOW
MySQL функция NOW возвращает текущую дату и время.
PERIOD_ADD
MySQL функция PERIOD_ADD принимает период (отформатированный как YYMM или YYYYMM) и добавляет к нему определенное количество месяцев.
PERIOD_DIFF
MySQL функция PERIOD_DIFF возвращает разность в месяцах между двумя периодами (отформатированная как YYMM или YYYYMM).
QUARTER
MySQL функция QUARTER возвращает числовое значение квартала год из даты.
SEC_TO_TIME
MySQL функция SEC_TO_TIME преобразует секунды в значение времени.
SECOND
MySQL функция SECOND возвращает количество секунд из значения даты.
STR_TO_DATE
MySQL функция STR_TO_DATE преобразует строку в дату, определенного формата.
SUBDATE
MySQL функция SUBDATE возвращает дату, после которой вычитается определенный интервал.
SUBTIME
MySQL функция SUBTIME возвращает значение даты/времени и времени, после которого вычитается определенный интервал времени.
SYSDATE
MySQL функция SYSDATE возвращает текущую дату и время.
TIME
MySQL функция TIME извлекает значение времени из выражения дата/время и время.
TIME_FORMAT
MySQL функция TIME_FORMAT форматирует время, указанное маской формата.
TIME_TO_SEC
MySQL функция TIME_TO_SEC преобразует значение времени в количество секунд.
TIMEDIFF
MySQL функция TIMEDIFF возвращает разность между двумя значениями даты / времени.
TIMESTAMP
MySQL функция TIMESTAMP преобразует выражение в значение даты и времени, и если задано, добавляется необязательный временной интервал для этого значения.
TO_DAYS
MySQL функция TO_DAYS преобразует дату в количество дней от нулевого года.
WEEK
Функция MySQL WEEK возвращает неделю года для значения даты.
WEEKDAY
MySQL функция WEEKDAY возвращает индекс дня недели.
WEEKOFYEAR
MySQL функция MySQL WEEKOFYEAR возвращает номер недели года для значения даты.
YEAR
MySQL функция YEAR возвращает год из значения даты.
YEARWEEK
MySQL функция YEARWEEK возвращает год и неделю для значения даты.

oracleplsql.ru

Форматы времени в MySQL: TIMESTAMP vs DATE[TIME]

В MySQL 5 есть несколько типов данных для хранения даты и времени. Это TIMESTAMP, DATE, DATETIME, TIME и YEAR. Все они обладают своими особенностями, и выбор в пользу того или иного календарного типа должен производиться отдельно в каждой конкретной ситуации. Я хотел бы поделиться с вами результатом моего сегодняшнего миниисследования этих типов, в том числе в аспекте работы с временными зонами.Итак, все календарные типы данных подробно описаны в разделе «10.3. Date and Time Types» руководства по MySQL. А важная информация, касающаяся поддержки СУБД временных зон, расписана в разделе «9.7. MySQL Server Time Zone Support». Все следующее далее базируется на изучении руководства. В то же время, в здесь указаны лишь нюансы выбора в пользу того или иного типа, поэтому этот материал никак не заменяет мануал, но дополняет его.

Вначале краткая характеристика каждого из типов:

  • TIMESTAMP — тип данных для хранения даты и времени. Данные хранятся в виде количества секунд, прошедших с начала «эпохи Юникса». Диапазон значений: 1970-01-01 00:00:00 — 2038-12-31 00:00:00. Занимает 4 байта.
  • YEAR — тип данных для хранения года. Диапазон значений: 1901 — 2155. Занимает 1 байт.
  • DATE — тип данных для хранения даты. Диапазон значений: 1000-01-01 — 9999-12-31. Занимает 3 байта.
  • TIME — тип данных для хранения времени. Диапазон значений: −828:59:59 — 828:59:59. Занимает 3 байта.
  • DATETIME — тип данных для хранения даты и времени. Диапазон значений: 1000-01-01 00:00:00 — 9999-12-31 00:00:00. Занимает 8 байт.

Хозяйке на заметку. Интересно то, что большинство программистов полагают, что понятие «timestamp» — это и есть Unix-время. На самом же деле, timestamp — это метка, которая представляет собой последовательность символов, обозначающих дату и / или время, когда определенное событие произошло. А «время Юникса» (Unix time) или POSIX time — это количество секунд, прошедших с полуночи 1 января 1970 года по UTC. Понятие timestamp шире, чем Unix time.

Проанализировав описание типов, представленное выше, можно сделать практически все выводы о достоинствах и недостатках тех или иных типов. Все довольно просто и очевидно.

Но прежде, чем рассказать об использовании этих типов, хочу заметить, что на практике часто используется другой тип для хранения даты и времени: целочисленное значение (для хранения даты — INT (4 байта), даты и времени — BIGINT (8 байт)). Отличие использования целочисленных типов от DATE и DATETIME лишь в том, что при выводе данные не форматируются, а в вычислениях с датами и временем целые числа требуется преобразовывать в соответствующий календарный тип. Кроме того, не производится проверка на валидность представленного значения перед сохранением. Возможности сортировки сохраняются. Поэтому INT и BIGINT имеет смысл использовать в тех же случаях, как DATE и DATETIME, с целью максимизации переносимости и независимости от СУБД. Других преимуществ я не вижу, если они есть, предлагаю указать в комментах.

Использование календарных типов данный в MySQL

Начнем с самого простого — тип YEAR. Единственное его достоинство — малый размер — всего-то 1 байт. Но из-за этого действует строгое ограничение по диапазону допустимых значений (тип может хранить только 255 разных значений). Мне сложно представить практическую ситуацию, когда может потребоваться хранить года строго в диапазоне от 1901 до 2155. Кроме того, тип SMALLINT (2 байта) дает диапазон, достаточный в большинстве ситуаций для хранения года. А экономить 1 байт на строке в таблице БД в наше время смысла нет.

Типы DATE и DATETIME можно объединить в одну группу. Они хранят дату или дату и время с довольно широким диапазоном допустимых значений, независимую от установленной на сервере временной зоны. Их использование определенно имеет практический смысл. Но если требуется хранить даты исторических событий, уходящие в прошлое за Нашу эру, придется выбрать другие типы данных. Для хранения дат неких событий, потенциально выходящих за рамки диапазона типа TIMESTAMP (дни рождений, даты выпуска продуктов, избрания президентов, запуски космических ракет и т.д.), отлично подойдут эти типы. При использовании этих типов нужно учитывать один важный нюанс, но об этом ниже.

Тип TIME можно использовать для хранения промежутка времени, когда не нужна точность меньше 1 секунды, и промежутки времени меньше 829 часов. Добавить тут больше нечего.

Остался самый интересный тип — TIMESTAMP. Рассматривать его надо в сравнении с DATE и DATETIME: TIMESTAMP тоже предназначен для хранения даты и/или времени происхождения неких событий. Важное отличие между ними в диапазонах значений: очевидно, что TIMESTAMP не годится для хранения исторических событий (даже таких, как дни рождений), но отлично подходит для хранения текущих (логирование, даты размещения статей, добавления товаров, оформления заказов) и предстоящих в обозримом будущем событий (выходы новых версий, календари и планировщики и т.д).

Основное удобство использования типа TIMESTAMP состоит в том, что для столбцов этого типа в таблицах можно задавать значение по умолчанию в виде подстановки текущего времени, а так же установки текущего времени при обновлении записи. Если вам требуется эти возможности, то с вероятностью 99% TIMESTAMP — именно то, что вам нужно. (Как этоделать, смотрите в мануале.)

Не стоит бояться того, что с приближением к 2038 году ваш софт перестанет работать. Во-первых, до этого времени вашим софтом, скорее всего, просто перестанут пользоваться (особенно версиями, которые пишутся сейчас). Во-вторых, с приближением к этой дате разработчики MySQL обязательно что-нибудь придумают для сохранения работоспособности вашего софта. Все решится так же хорошо, как проблема Y2K.

Итак, тип TIMESTAMP используем для хранения дат и времени свершения событий нашего времени, а DATETIME и DATE — для хранения дат и времени свершения исторических событий, или событий глубокого будущего.

Диапазоны значений — это важное отличие между типами TIMESTAMP, DATETIME и DATE, но не главное. Главное то, что TIMESTAMP хранит значение в UTC. При сохранении значения оно переводится из текущего временной зоны в UTC, а при его чтении — во время текущей временной зоны из UTC. DATETIME и DATE хранят и выводят всегда одно и то же время, независимо от временных зон.

Временные зоны устанавливаются в СУБД MySQL глобально или для текущего подключения.Последнее можно использовать для обеспечения работы разных пользователей в разных временных зонах на уровне СУБД. Все значения времени физически будут храниться в UTC, а приниматься от клиента и отдаваться клинту — в значениях его временной зоны. Но только при использовании типа данных TIMESTAMP. DATE и DATETIME всегда принимают, хранят и отдают одно и то же значение.

Функция NOW() и ее синонимы возвращают значение времени в текущей временной зоне пользователя.

Учитывая все эти обстоятельства, необходимо быть крайне внимательными при изменении временной зоны в пределах подключения к серверу и использовании типов DATE и DATETIME. Если надо хранить дату (например, дату рождения), то никаких проблем не будет. Дата рождения в любой зоне одинаковая. Т.е. если вы родились 1 января в 0:00 UTC/GMT+0, то это не значит, что в Америке будут праздновать ваш день рождения 31 декабря. Но если вы решите хранить время события в столбце DATETIME, то тут уже построить работу с пользовательскими временными зонами на уровне СУБД просто не выйдет. Поясню на примере:

Пользователь X работает в зоне UTC/GMT+2, Y — в зоне UTC/GMT+3. Для соединений пользователей с MySQL установлена соответствующая (у каждого своя) временная зона. Пользователь размещает сообщение на форуме, нас интересует дата написания сообщения.

Вариант 1: DATETIME. Пользователь X пишет сообщение в 14:00 UTC/GMT+2. Значение в поле «дата» сообщения подставляется как результат выполнения функции NOW() — 14:00. Пользователь Y считывает время написания сообщения и видит те же 14:00. Но у него в настройках стоитзона UTC/GMT+3, и он думает, что сообщение было написано не только что, а час назад.

Вариант 2: TIMESTAMP. Пользователь X пишет сообщение в 14:00 UTC/GMT+2. В поле «дата» попадает результат выполнения функции NOW() — в данном случае — 12:00 UTC/GMT+0. ПользовательY считывает время написания сообщения и получает (UTC/GMT+3)(12:00 UTC/GMT+0) = 15:00 UTC/GMT+3. Все получается ровно так, как мы хотим. И главное — пользоваться этим крайне удобно: для поддержки пользовательских временных зон не нужно писать никакой код приведения времени.

Возможности подстановки текущего времени и работы с временными зонами в типе TIMESTAMP настолько весомы, что если вам в неком логе надо хранить дату без времени, все равно стоит использовать TIMESTAMP, вместо DATE, не экономя 1 байт разницы между ними. При этом на «00:00:00» просто не обращать внимания.

Если же вы не можете использовать TIMESTAMP из-за относительно малого диапазона его значений (а обычно это 1—2 случая против 10—15 в базе сайта), придется использовать DATETIME и аккуратно его корректировать значения в нужных местах (т.е. при записи в это поле переводить дату в UTC, а при чтении — во время в зоне считывающего пользователя). Если вы храните только дату, то скорее всего не важно, какая у вас временная зона: новый год все празднуют 1 января по локальному времени, ничего переводить тут не понадобится.

valera.ws