Ответ 1
Кажется, что не имеет значения, какой часовой пояс находится на сервере, если у вас есть время, установленное правильно для текущего часового пояса, знать часовой пояс столбцов datetime, которые вы храните, и осведомлены о проблемах с летней экономией время.
С другой стороны, если у вас есть контроль над часовыми поясами серверов, с которыми вы работаете, вы можете настроить все настройки на UTC внутри себя и никогда не беспокоиться о часовых поясах и DST.
Вот некоторые примечания, которые я собрал о том, как работать с часовыми поясами, как форму чит-листа для себя и других, которые могут повлиять на то, какой часовой пояс выберете для своего сервера, и как он будет хранить дату и время.
Шифрование часовых поясов MySQL
Примечания:
- Изменение часового пояса не изменит хранимое время datetime или timestamp, но он выберет другое время и время от столбцы с меткой времени
- UTC не использует летнее время, GMT (регион), GMT (часовой пояс) не работает (GMT также вводит в заблуждение определение секунд, поэтому был разработан UTC).
- Предупреждение! UTC имеет секунды прыжка, они выглядят так: '2012-06-30 23:59:60' и могут быть добавлен случайным образом, с предварительным уведомлением за 6 месяцев, из-за замедления вращение Земли
- Предупреждение! разные региональные часовые пояса могут вызывать одинаковое значение даты и времени из-за на летнее время
- Столбец с меткой времени поддерживает только даты 1970-01-01 00:00:01 до 2038-01-19 03:14:07 UTC
-
Внутри Столбец timestamp MySQL сохраняется как UTC но при выборе даты MySQL автоматически преобразует ее в текущий часовой пояс сеанса.
При сохранении даты в метке времени MySQL будет считать, что дата находится в текущем часовом поясе сессии и конвертирует его в UTC для хранения.
- MySQL может хранить частичные даты в столбцах datetime, они выглядят как "2013-00-00 04:00:00"
- MySQL хранит "0000-00-00 00:00:00", если вы установите столбец datetime как NULL, если вы специально не задали для столбца значение null, когда вы создайте его.
- Прочтите это
Чтобы выбрать столбец временной метки в формате UTC
независимо от того, в какой временной зоне находится текущий сеанс MySQL:
SELECT
CONVERT_TZ(`timestamp_field`, @@session.time_zone, '+00:00') AS `utc_datetime`
FROM `table_name`
Вы также можете установить часовой пояс или глобальный или текущий сеансовый часовой пояс в UTC, а затем выбрать временную метку следующим образом:
SELECT `timestamp_field` FROM `table_name`
Чтобы выбрать текущее время в UTC:
SELECT UTC_TIMESTAMP();
SELECT UTC_TIMESTAMP;
SELECT CONVERT_TZ(NOW(), @@session.time_zone, '+00:00');
Результат: 2015-03-24 17:02:41
Чтобы выбрать текущее время и время в часовом поясе сеанса
SELECT NOW();
SELECT CURRENT_TIMESTAMP;
SELECT CURRENT_TIMESTAMP();
Чтобы выбрать часовой пояс, который был установлен при запуске сервера
SELECT @@system_time_zone;
Возвращает "MSK" или "+04: 00" для московского времени, например, есть (или была) ошибка MySQL, где, если она установлена на числовое смещение, она не будет корректировать переход на летнее время
Чтобы получить текущий часовой пояс
SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP);
Он вернется в 02:00:00, если ваш часовой пояс равен +2: 00.
Чтобы получить текущую временную метку UNIX (в секундах):
SELECT UNIX_TIMESTAMP(NOW());
SELECT UNIX_TIMESTAMP();
Чтобы получить столбец timestamp как отметку времени UNIX
SELECT UNIX_TIMESTAMP(`timestamp`) FROM `table_name`
Чтобы получить столбец datetime UTC как временную метку UNIX
SELECT UNIX_TIMESTAMP(CONVERT_TZ(`utc_datetime`, '+00:00', @@session.time_zone)) FROM `table_name`
Получить текущий часовой пояс datetime с положительной метки времени UNIX
SELECT FROM_UNIXTIME(`unix_timestamp_int`) FROM `table_name`
Получить UTC datetime из отметки времени UNIX
SELECT CONVERT_TZ(FROM_UNIXTIME(`unix_timestamp_int`), @@session.time_zone, '+00:00')
FROM `table_name`
Получить текущее время и время часового пояса от отрицательного UNIX timestamp integer
SELECT DATE_ADD('1970-01-01 00:00:00',INTERVAL -957632400 SECOND)
Есть 3 места, где временной интервал может быть установлен в MySQL:
Примечание. Часовой пояс можно установить в двух форматах:
- смещение от UTC: '+00: 00', '+10: 00' или '-6: 00'
- как названный часовой пояс: "Европа/Хельсинки", "США/Восток" или "МЕТ"
Именованные часовые пояса могут использоваться только в том случае, если таблицы информации о часовом поясе в базе данных mysql были созданы и заполнены.
в файле "my.cnf"
default_time_zone='+00:00'
или
timezone='UTC'
@@global.time_zone variable
Чтобы узнать, на какое значение они установлены на
SELECT @@global.time_zone;
Чтобы установить для него значение, используйте один из них:
SET GLOBAL time_zone = '+8:00';
SET GLOBAL time_zone = 'Europe/Helsinki';
SET @@global.time_zone='+00:00';
@@session.time_zone variable
SELECT @@session.time_zone;
Чтобы установить его, используйте один из них:
SET time_zone = 'Europe/Helsinki';
SET time_zone = "+00:00";
SET @@session.time_zone = "+00:00";
как "@@global.time_zone variable", так и "@@session.time_zone variable" могут возвращать "SYSTEM", что означает, что они используют часовой пояс, установленный в "my.cnf".
Для того, чтобы названия часовых поясов работали (даже для зоны по умолчанию-времени), вы должны настроить таблицы информации о часовом поясе, которые необходимо заполнить: http://dev.mysql.com/doc/refman/5.1/en/time-zone-support.html
Примечание: вы не можете сделать это, так как он вернет NULL:
SELECT
CONVERT_TZ(`timestamp_field`, TIMEDIFF(NOW(), UTC_TIMESTAMP), '+00:00') AS `utc_datetime`
FROM `table_name`
Настройка таблиц часовых поясов mysql
Для работы CONVERT_TZ
вам понадобятся таблицы часовых поясов, которые будут заполнены
SELECT * FROM mysql.`time_zone` ;
SELECT * FROM mysql.`time_zone_leap_second` ;
SELECT * FROM mysql.`time_zone_name` ;
SELECT * FROM mysql.`time_zone_transition` ;
SELECT * FROM mysql.`time_zone_transition_type` ;
Если они пусты, заполните их, выполнив эту команду
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
если эта команда дает вам ошибку "данные слишком долго для сокращения абзаца столбца в строке 1 ", то это может быть вызвано NULL-символ добавляется в конце аббревиатуры часового пояса
Исправление состоит в том, чтобы запустить этот
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
(if the above gives error "data too long for column 'abbreviation' at row 1")
mysql_tzinfo_to_sql /usr/share/zoneinfo > /tmp/zut.sql
echo "SET SESSION SQL_MODE = '';" > /tmp/mysql_tzinfo_to.sql
cat /tmp/zut.sql >> /tmp/mysql_tzinfo_to.sql
mysql --defaults-file=/etc/mysql/my.cnf --user=verifiedscratch -p mysql < /tmp/mysql_tzinfo_to.sql
(убедитесь, что ваши правила dst для серверов обновлены zdump -v Europe/Moscow | grep 2011
https://chrisjean.com/updating-daylight-saving-time-on-linux/)
См. полную историю перехода DST (переход на летнее время) для каждого часового пояса
SELECT
tzn.Name AS tz_name,
tztt.Abbreviation AS tz_abbr,
tztt.Is_DST AS is_dst,
tztt.`Offset` AS `offset`,
DATE_ADD('1970-01-01 00:00:00',INTERVAL tzt.Transition_time SECOND) AS transition_date
FROM mysql.`time_zone_transition` tzt
INNER JOIN mysql.`time_zone_transition_type` tztt USING(Time_zone_id, Transition_type_id)
INNER JOIN mysql.`time_zone_name` tzn USING(Time_zone_id)
-- WHERE tzn.Name LIKE 'Europe/Moscow' -- Moscow has weird DST changes
ORDER BY tzt.Transition_time ASC
CONVERT_TZ
также применяет любые необходимые изменения DST на основе правил в приведенных выше таблицах и даты, которую вы используете.
Примечание:
Согласно docs, значение, которое вы задали для time_zone, не изменяется, если вы установите его как "+01: 00", например, time_zone будет устанавливаться как смещение от UTC, которое не следует за DST, поэтому оно будет оставаться неизменным круглый год.
Только имя timezones изменяет время в течение летнего времени.
Сокращения, такие как CET
, всегда будут зимним временем, а CEST
будет летним, тогда как +01: 00 всегда будет UTC
время + 1 час, и оба они не изменятся с помощью DST.
Часовой пояс system
будет часовым поясом хост-машины, на которой установлена mysql (если mysql не может ее определить)
Вы можете больше узнать о работе с DST здесь
связанные вопросы:
- Как установить часовой пояс MySQL?
- MySql - SELECT Столбец TimeStamp в формате UTC
- Как получить временную метку Unix в MySQL от UTC?
- Преобразование MySQL MySQL TimeStamp в UTC
- https://dba.stackexchange.com/questions/20217/mysql-set-utc-time-as-default-timestamp
- Как получить текущий часовой пояс MySQL?
- MySQL datetime fields и летнее время - как я могу ссылаться на" extra " час?
- Преобразование отрицательных значений из FROM_UNIXTIME
Источники:
- https://bugs.mysql.com/bug.php?id=68861
- http://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html
- http://dev.mysql.com/doc/refman/5.1/en/datetime.html
- http://en.wikipedia.org/wiki/Coordinated_Universal_Time
- http://shafiqissani.wordpress.com/2010/09/30/how-to-get-the-current-epoch-time-unix-timestamp/
- https://web.ivy.net/~carton/rant/MySQL-timezones.txt