DATE
、DATETIME
、および TIMESTAMP
型は関連しています。 このセクションでは、これらの特徴、似ている点、および異なる点について説明します。 MySQL は、セクション9.1.3「日付リテラルと時間リテラル」で説明している複数の形式で、DATE
、DATETIME
、および TIMESTAMP
値を認識します。 DATE
および DATETIME
範囲の説明では、「サポートされている」とは、以前の値は機能するが、保証はないということを意味します。
DATE
型は、日付部分を含むが時間部分は含まない値に使用されます。 MySQL は、DATE
値を'
形式で取得して表示します。 サポートしている範囲は YYYY-MM-DD
''1000-01-01'
から '9999-12-31'
です。
DATETIME
型は、日付と時間の両方の部分を含む値に使用されます。 MySQL は、DATETIME
値を'
形式で取得して表示します。 サポートしている範囲は YYYY-MM-DD hh:mm:ss
''1000-01-01 00:00:00'
から '9999-12-31 23:59:59'
です。
TIMESTAMP
データ型は、日付と時間の両方の部分を含む値に使用されます。 TIMESTAMP
には、'1970-01-01 00:00:01'
UTC から '2038-01-19 03:14:07'
UTC の範囲があります。
DATETIME
または TIMESTAMP
値には、マイクロ秒 (6 桁) までの精度で後続の小数秒部分を含めることができます。 特に、DATETIME
または TIMESTAMP
カラムに挿入された値の小数部は、破棄されるのではなく格納されます。 小数部が含まれている場合、これらの値の書式は'
、YYYY-MM-DD hh:mm:ss
[.fraction
]'DATETIME
値の範囲は'1000-01-01 00:00:00.000000'
から'9999-12-31 23:59:59.999999'
、TIMESTAMP
値の範囲は'1970-01-01 00:00:01.000000'
から'2038-01-19 03:14:07.999999'
です。 小数部は、常に時間の残りの部分から小数点で区分する必要があります。これ以外の小数秒区切り文字は認識されません。 MySQL の小数秒のサポートの詳細は、セクション11.2.6「時間値での小数秒」を参照してください。
TIMESTAMP
および DATETIME
データ型は、現在の日時への自動初期化および更新を提供します。 詳細は、セクション11.2.5「TIMESTAMP および DATETIME の自動初期化および更新機能」を参照してください。
MySQL は、TIMESTAMP
値を、ストレージでは現在のタイムゾーンを UTC に変換し、取得では UTC から現在のタイムゾーンに戻します。 (DATETIME
などのほかの型ではこれは行われません。) デフォルトでは、接続ごとの現在のタイムゾーンはサーバーの時間です。 タイムゾーンは接続ごとに設定できます。 タイムゾーン設定が一定であるかぎり、格納した値と同じ値に戻すことができます。 TIMESTAMP
値を格納したあとで、タイムゾーンを変更して値を取り出すと、取り出された値は格納した値とは異なります。 これは、同じタイムゾーンが両方向への変換に使用されなかったために起こります。 現在のタイムゾーンは、time_zone
システム変数の値として使用できます。 詳細は、セクション5.1.15「MySQL Server でのタイムゾーンのサポート」を参照してください。
MySQL 8.0.19 では、TIMESTAMP
および DATETIME
の値をテーブルに挿入するときにタイムゾーンオフセットを指定できます。 オフセットは、内部スペースを使用せずに日時リテラルの時間部分に追加され、time_zone
システム変数の設定に使用されるのと同じ書式を使用しますが、次の例外があります:
10 未満の時間値の場合、先行するゼロが必要です。
値
'-00:00'
は拒否されます。'EET'
や'Asia/Shanghai'
などのタイムゾーン名は使用できません。このコンテキストでは'SYSTEM'
も使用できません。
挿入される値は、月、日、またはその両方の部分に対してゼロを持つことはできません。 これは、サーバーの SQL モードの設定に関係なく、MySQL 8.0.22 以降で強制されます。
この例では、異なる time_zone
設定を使用してタイムゾーンオフセットを含む日時値を TIMESTAMP
および DATETIME
カラムに挿入し、それらを取得する方法を示します:
mysql> CREATE TABLE ts (
-> id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> col TIMESTAMP NOT NULL
-> ) AUTO_INCREMENT = 1;
mysql> CREATE TABLE dt (
-> id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> col DATETIME NOT NULL
-> ) AUTO_INCREMENT = 1;
mysql> SET @@time_zone = 'SYSTEM';
mysql> INSERT INTO ts (col) VALUES ('2020-01-01 10:10:10'),
-> ('2020-01-01 10:10:10+05:30'), ('2020-01-01 10:10:10-08:00');
mysql> SET @@time_zone = '+00:00';
mysql> INSERT INTO ts (col) VALUES ('2020-01-01 10:10:10'),
-> ('2020-01-01 10:10:10+05:30'), ('2020-01-01 10:10:10-08:00');
mysql> SET @@time_zone = 'SYSTEM';
mysql> INSERT INTO dt (col) VALUES ('2020-01-01 10:10:10'),
-> ('2020-01-01 10:10:10+05:30'), ('2020-01-01 10:10:10-08:00');
mysql> SET @@time_zone = '+00:00';
mysql> INSERT INTO dt (col) VALUES ('2020-01-01 10:10:10'),
-> ('2020-01-01 10:10:10+05:30'), ('2020-01-01 10:10:10-08:00');
mysql> SET @@time_zone = 'SYSTEM';
mysql> SELECT @@system_time_zone;
+--------------------+
| @@system_time_zone |
+--------------------+
| EST |
+--------------------+
mysql> SELECT col, UNIX_TIMESTAMP(col) FROM dt ORDER BY id;
+---------------------+---------------------+
| col | UNIX_TIMESTAMP(col) |
+---------------------+---------------------+
| 2020-01-01 10:10:10 | 1577891410 |
| 2019-12-31 23:40:10 | 1577853610 |
| 2020-01-01 13:10:10 | 1577902210 |
| 2020-01-01 10:10:10 | 1577891410 |
| 2020-01-01 04:40:10 | 1577871610 |
| 2020-01-01 18:10:10 | 1577920210 |
+---------------------+---------------------+
mysql> SELECT col, UNIX_TIMESTAMP(col) FROM ts ORDER BY id;
+---------------------+---------------------+
| col | UNIX_TIMESTAMP(col) |
+---------------------+---------------------+
| 2020-01-01 10:10:10 | 1577891410 |
| 2019-12-31 23:40:10 | 1577853610 |
| 2020-01-01 13:10:10 | 1577902210 |
| 2020-01-01 05:10:10 | 1577873410 |
| 2019-12-31 23:40:10 | 1577853610 |
| 2020-01-01 13:10:10 | 1577902210 |
+---------------------+---------------------+
日時値の選択時にオフセットが使用された場合でも、オフセットは表示されません。
サポートされるオフセット値の範囲は、-14:00
から +14:00
までです。
タイムゾーンオフセットを含む日時リテラルは、プリペアドステートメントによってパラメータ値として受け入れられます。
SQL モードでこの変換が許可されている場合、無効な DATE
、DATETIME
または TIMESTAMP
値は適切なタイプ ('0000-00-00'
または'0000-00-00 00:00:00'
) の「「ゼロ」」値に変換されます。 正確な動作は、厳密な SQL モードと NO_ZERO_DATE
SQL モードのいずれかが有効かどうかによって異なります。セクション5.1.11「サーバー SQL モード」 を参照してください。
MySQL 8.0.22 以降では、次に示すように CAST()
を AT TIME ZONE
演算子とともに使用して取得するときに、TIMESTAMP
値を UTC DATETIME
値に変換できます:
mysql> SELECT col,
> CAST(col AT TIME ZONE INTERVAL '+00:00' AS DATETIME) AS ut
> FROM ts ORDER BY id;
+---------------------+---------------------+
| col | ut |
+---------------------+---------------------+
| 2020-01-01 10:10:10 | 2020-01-01 15:10:10 |
| 2019-12-31 23:40:10 | 2020-01-01 04:40:10 |
| 2020-01-01 13:10:10 | 2020-01-01 18:10:10 |
| 2020-01-01 10:10:10 | 2020-01-01 15:10:10 |
| 2020-01-01 04:40:10 | 2020-01-01 09:40:10 |
| 2020-01-01 18:10:10 | 2020-01-01 23:10:10 |
+---------------------+---------------------+
構文およびその他の例の詳細は、CAST()
関数の説明を参照してください。
MySQL では日付値解釈の特定のプロパティーに注意してください。
-
MySQL は、文字列として指定された値に、「緩やかな」形式を使用でき、この形式では、どの句読点文字でも日付部分と時間部分の区切り文字として使用できます。 場合によっては、この構文は偽りになることがあります。 たとえば、
'10:11:12'
などの値は、:
が原因で時間値のように見えますが、日付コンテキストで使用されている場合は'2010-11-12'
年として解釈されます。 値'10:45:15'
は、'45'
が有効な月ではないので、'0000-00-00'
に変換されます。日付および時間の部分と小数秒部分との間の区切り文字として認識される唯一の文字が小数点です。
サーバーは、月と日の値が、それぞれが 1 から 12 と 1 から 31 の範囲内にあるだけではなく、有効である必要があります。 厳密モードが無効になっていると、
'2004-04-31'
のような無効な日付は'0000-00-00'
に変換され、警告メッセージが表示されます。 厳密モードが有効なときは、無効な日付によってエラーが発生します。 このような日付を許可するには、ALLOW_INVALID_DATES
を有効にします。 詳細は、セクション5.1.11「サーバー SQL モード」を参照してください。MySQL は、日または月カラムにゼロを含んだ
TIMESTAMP
値や、無効な日付の値を受け入れません。 SQL モードでこの値が許可されている場合、このルールの唯一の例外は、特別な「「ゼロ」」値'0000-00-00 00:00:00'
です。 正確な動作は、厳密な SQL モードとNO_ZERO_DATE
SQL モードのいずれかが有効かどうかによって異なります。セクション5.1.11「サーバー SQL モード」 を参照してください。-
世紀が不明であるため、2 桁の年の値を含む日付はあいまいです。 MySQL は、次のルールを使用して 2 桁の年の値を解釈します:
00-69
の範囲内の年の値は2000-2069
になります。70-99
の範囲内の年の値は1970-1999
になります。
セクション11.2.8「日付の 2 桁の年」も参照してください。