https://serverfault.com/questions/191331/should-servers-have-their-timezone-set-to-gmt-utcのフォローアップの質問
MySQL のタイムゾーンを UTC に設定する必要がありますか、それともサーバーまたは PHP の設定と同じタイムゾーンに設定する必要がありますか? (UTCでない場合)
長所と短所は何ですか?
https://serverfault.com/questions/191331/should-servers-have-their-timezone-set-to-gmt-utcのフォローアップの質問
MySQL のタイムゾーンを UTC に設定する必要がありますか、それともサーバーまたは PHP の設定と同じタイムゾーンに設定する必要がありますか? (UTCでない場合)
長所と短所は何ですか?
現在のタイムゾーンに合わせて時刻が正しく設定されていて、保存する日時列のタイムゾーンを知っていて、夏時間の問題を認識している限り、サーバー上のタイムゾーンは問題ではないようです。
一方、使用するサーバーのタイムゾーンを制御できる場合は、内部ですべてを UTC に設定することができ、少なくとも内部時間の保存に関しては、タイムゾーンと DST について心配する必要はありません。
以下は、自分自身や他の人が自分のサーバーに選択するタイムゾーンと、日付と時刻を保存する方法に影響を与える可能性のあるチートシートの形式としてタイムゾーンを操作する方法について収集したメモです。
ノート:
タイムゾーンを変更しても、保存されている datetime または timestamp は変更されませんが、timestamp 列から別の datetime が選択されます
警告!UTC にはうるう秒があり、これらは「2012-06-30 23:59:60」のように表示され、地球の自転が遅くなるため、6 か月前に通知することでランダムに追加できます。
GMT は秒を混乱させるため、UTC が発明されました。
警告!異なる地域のタイムゾーンは、夏時間のために同じ datetime 値を生成する場合があります
タイムスタンプ列は、制限により、1970-01-01 00:00:01 から 2038-01-19 03:14:07 UTC の日付のみをサポートします。
内部的にMySQL タイムスタンプ列はUTCとして保存されますが、日付を選択すると、MySQL は自動的に現在のセッションのタイムゾーンに変換します。
日付をタイムスタンプに保存する場合、MySQL は日付が現在のセッションのタイムゾーンにあると想定し、保存のために UTC に変換します。
MySQL は datetime 列に部分的な日付を格納できます。これらは "2013-00-00 04:00:00" のようになります。
datetime カラムを NULL として設定すると、MySQL は「0000-00-00 00:00:00」を格納します。ただし、カラムを作成するときに特に null を許可するように設定しない限りは、.
現在の MySQL セッションがどのタイムゾーンにあるかに関係なく:
SELECT
CONVERT_TZ(`timestamp_field`, @@session.time_zone, '+00:00') AS `utc_datetime`
FROM `table_name`
サーバーまたはグローバルまたは現在のセッションのタイムゾーンを UTC に設定してから、次のようにタイムスタンプを選択することもできます。
SELECT `timestamp_field` FROM `table_name`
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);
タイムゾーンが +2:00 の場合、02:00:00 が返されます。
SELECT UNIX_TIMESTAMP(NOW());
SELECT UNIX_TIMESTAMP();
SELECT UNIX_TIMESTAMP(`timestamp`) FROM `table_name`
SELECT UNIX_TIMESTAMP(CONVERT_TZ(`utc_datetime`, '+00:00', @@session.time_zone)) FROM `table_name`
SELECT FROM_UNIXTIME(`unix_timestamp_int`) FROM `table_name`
SELECT CONVERT_TZ(FROM_UNIXTIME(`unix_timestamp_int`), @@session.time_zone, '+00:00')
FROM `table_name`
SELECT DATE_ADD('1970-01-01 00:00:00',INTERVAL -957632400 SECOND)
注: タイムゾーンは 2 つの形式で設定できます。
名前付きタイム ゾーンは、mysql データベース内のタイム ゾーン情報テーブルが作成され、入力されている場合にのみ使用できます。
default_time_zone='+00:00'
また
timezone='UTC'
設定されている値を確認するには
SELECT @@global.time_zone;
値を設定するには、次のいずれかを使用します。
SET GLOBAL time_zone = '+8:00';
SET GLOBAL time_zone = 'Europe/Helsinki';
SET @@global.time_zone='+00:00';
SELECT @@session.time_zone;
設定するには、次のいずれかを使用します。
SET time_zone = 'Europe/Helsinki';
SET time_zone = "+00:00";
SET @@session.time_zone = "+00:00";
「@@global.time_zone 変数」と「@@session.time_zone 変数」の両方が「SYSTEM」を返す場合があります。これは、「my.cnf」で設定されたタイムゾーンを使用することを意味します。
タイムゾーン名を機能させるには (default-time-zone でも)、タイムゾーン情報テーブルを設定する必要があります: 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`
機能するには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
このコマンドで「data too long for column 'abbreviation' at row 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/ )
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 は DST に従わない UTC からのオフセットとして設定されるため、それは一年中同じままです。
名前付きのタイムゾーンのみが夏時間中に時間を変更します。
のような略語CET
は常に冬時間で夏時間CEST
になりますが、+01:00 は常にUTC
時間 + 1 時間であり、どちらも DST によって変わりません。
system
タイムゾーンは、mysql がインストールされているホスト マシンのタイムゾーンになります (mysql が決定に失敗しない限り) 。
DST の操作について詳しくは、こちらをご覧ください。
伝説の Jon Skeet による UTC を使用しない場合: https://codeblog.jonskeet.uk/2019/03/27/storing-utc-is-not-a-silver-bullet/ (たとえば、将来予定されているイベント瞬間ではなく時間を表す)
関連する質問:
ソース:
PHP と MySQL には、独自のデフォルトのタイムゾーン構成があります。データベースと Web アプリケーションの間で時刻を同期する必要があります。そうしないと、問題が発生する可能性があります。
このチュートリアルを読む: PHP と MySQL のタイムゾーンを同期する方法