sql >> データベース >  >> RDS >> Mysql

MySQLのタイムゾーンをUTCに設定する必要がありますか?

    現在のタイムゾーンに適切な時刻が設定されていて、保存する日時列のタイムゾーンがわかっていて、夏時間の問題を認識している限り、サーバー上のタイムゾーンは問題ではないようです。

    一方、使用するサーバーのタイムゾーンを制御できる場合は、すべてを内部でUTCに設定でき、タイムゾーンとDSTについて心配する必要はありません。

    これは、自分自身と他の人のチートシートの形式としてタイムゾーンを操作する方法について収集したメモです。これは、サーバー用に選択するタイムゾーンと、日付と時刻の保存方法に影響を与える可能性があります。

    MySQLタイムゾーンのチートシート

    注:

    1. タイムゾーンを変更しても、保存されている日時やタイムスタンプは変更されません 、ただし、timestamp列から別の日時が選択されます

    2. 警告! UTCにはうるう秒があり、これらは「2012-06-30 23:59:60」のように見え、地球の自転が遅くなるため、6か月前に通知してランダムに追加できます

    3. GMTは秒を混乱させるため、UTCが発明されました。

    4. 警告! 地域のタイムゾーンが異なると、夏時間のために同じ日時の値が生成される可能性があります

    5. タイムスタンプ列は、制限

    6. 内部的には、MySQLタイムスタンプ列 UTC として保存されます ただし、日付を選択すると、MySQLはそれを現在のセッションタイムゾーンに自動的に変換します。

      タイムスタンプに日付を保存する場合、MySQLは日付が現在のセッションのタイムゾーンにあると想定し、保存のためにUTCに変換します。

    7. MySQLは、日付の一部を日時列に格納できます。これらは「2013-00-0004:00:00」のようになります

    8. 日時列をNULLとして設定した場合、作成時にnullを許可するように列を特に設定しない限り、MySQLは「0000-00-0000:00:00」を格納します。

    9. これを読む

    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);
    

    タイムゾーンが+2:00の場合、02:00:00が返されます。

    現在のUNIXタイムスタンプ(秒単位)を取得するには:

    SELECT UNIX_TIMESTAMP(NOW());
    SELECT UNIX_TIMESTAMP();
    

    タイムスタンプ列をUNIXタイムスタンプとして取得するには

    SELECT UNIX_TIMESTAMP(`timestamp`) FROM `table_name`
    

    UTC日時列をUNIXタイムスタンプとして取得するには

    SELECT UNIX_TIMESTAMP(CONVERT_TZ(`utc_datetime`, '+00:00', @@session.time_zone)) FROM `table_name`
    

    正のUNIXタイムスタンプ整数から現在のタイムゾーン日時を取得します

    SELECT FROM_UNIXTIME(`unix_timestamp_int`) FROM `table_name`
    

    UNIXタイムスタンプからUTC日時を取得する

    SELECT CONVERT_TZ(FROM_UNIXTIME(`unix_timestamp_int`), @@session.time_zone, '+00:00') 
    FROM `table_name`
    

    負のUNIXタイムスタンプ整数から現在のタイムゾーン日時を取得します

    SELECT DATE_ADD('1970-01-01 00:00:00',INTERVAL -957632400 SECOND) 
    

    MySQLでタイムゾーンが設定される可能性のある場所は3つあります:

    注:タイムゾーンは2つの形式で設定できます:

    1. UTCからのオフセット:「+ 00:00」、「+ 10:00」、または「-6:00」
    2. 名前付きタイムゾーンとして:「ヨーロッパ/ヘルシンキ」、「米国/東部」、または「MET」

    名前付きタイムゾーンは、mysqlデータベースのタイムゾーン情報テーブルが作成され、入力されている場合にのみ使用できます。

    ファイル「my.cnf」内

    default_time_zone='+00:00'
    

    または

    timezone='UTC'
    

    @@global.time_zone変数

    設定されている値を確認するには

    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変数

    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」で設定されたタイムゾーンを使用することを意味します。

    タイムゾーン名を機能させるには(デフォルトのタイムゾーンでも)、タイムゾーン情報テーブルにデータを入力する必要があります: 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の変更を適用します。

    注:
    ドキュメント> 、time_zoneに設定した値は変更されません。たとえば、「+ 01:00」に設定すると、time_zoneはDSTに従わないUTCからのオフセットとして設定されるため、すべて同じままになります。一年中。

    名前付きのタイムゾーン のみ 夏時間の間に時間を変更します。

    CETのような略語 常に冬時間であり、CEST +01:00は常にUTCであるのに対し、夏時間になります 時間+1時間で、どちらもDSTで変更されません。

    system タイムゾーンは、mysqlがインストールされているホストマシンのタイムゾーンになります(mysqlがそれを決定できない場合を除く)

    DSTの使用について詳しくは、こちら をご覧ください。

    伝説のジョンスキートがUTCを使用しない場合: https://codeblog.jonskeet.uk/2019/03/27/storing-utc-is-not-a-silver-bullet/ (たとえば、瞬間ではなく、時間を表す将来のスケジュールされたイベント)

    関連する質問:

    出典:



    1. 複数のチェックボックス値をテーブルに挿入するにはどうすればよいですか?

    2. Dockerコンテナ上のPostgreSQLデータベースに接続します

    3. Oracle:DDLとトランザクションのロールバック

    4. SQLServerでSELECTから更新する方法