MySQL 9.0 參考手冊  /  ...  /  日期和時間文字

11.1.3 日期和時間文字

日期和時間值可以用幾種格式表示,例如帶引號的字串或數字,具體取決於值的確切類型和其他因素。例如,在 MySQL 期望日期的情況下,它會將 '2015-07-21''20150721'20150721 都解釋為日期。

本節描述日期和時間文字的可接受格式。有關時間資料類型(例如允許的值範圍)的更多資訊,請參閱 第 13.2 節,「日期和時間資料類型」

標準 SQL 和 ODBC 日期和時間文字

標準 SQL 要求時間文字使用類型關鍵字和字串指定。關鍵字和字串之間的空格是可選的。

DATE 'str'
TIME 'str'
TIMESTAMP 'str'

MySQL 識別類型關鍵字,但與標準 SQL 不同,不需要類型關鍵字。要符合標準的應用程式應包含時間文字的類型關鍵字。

MySQL 還識別與標準 SQL 語法對應的 ODBC 語法

{ d 'str' }
{ t 'str' }
{ ts 'str' }

MySQL 使用類型關鍵字和 ODBC 建構來產生 DATETIMEDATETIME 值,包括尾隨的小數秒部分(如果指定)。TIMESTAMP 語法會在 MySQL 中產生 DATETIME 值,因為 DATETIME 的範圍更接近標準 SQL TIMESTAMP 類型,其年份範圍從 00019999。(MySQL TIMESTAMP 的年份範圍是 19702038。)

日期和時間環境中的字串和數值文字

MySQL 識別以下格式的 DATE

  • 作為 'YYYY-MM-DD''YY-MM-DD' 格式的字串。允許使用寬鬆語法,但已棄用:任何標點符號都可以用作日期部分之間的分隔符。例如,'2012-12-31''2012/12/31''2012^12^31''2012@12@31' 是等效的。使用破折號 (-) 以外的任何字元作為分隔符會引發警告,如下所示

    mysql> SELECT DATE'2012@12@31';
    +------------------+
    | DATE'2012@12@31' |
    +------------------+
    | 2012-12-31       |
    +------------------+
    1 row in set, 1 warning (0.00 sec)
    
    mysql> SHOW WARNINGS\G
    *************************** 1. row ***************************
      Level: Warning
       Code: 4095
    Message: Delimiter '@' in position 4 in datetime value '2012@12@31' at row 1 is
    deprecated. Prefer the standard '-'. 
    1 row in set (0.00 sec)
  • 作為沒有分隔符的 'YYYYMMDD''YYMMDD' 格式的字串,前提是該字串作為日期有意義。例如,'20070523''070523' 會被解釋為 '2007-05-23',但 '071332' 是非法的(它具有無意義的月份和日期部分)並變成 '0000-00-00'

  • 作為 YYYYMMDDYYMMDD 格式的數字,前提是該數字作為日期有意義。例如,19830905830905 會被解釋為 '1983-09-05'

MySQL 識別以下格式的 DATETIMETIMESTAMP

  • 作為 'YYYY-MM-DD hh:mm:ss''YY-MM-DD hh:mm:ss' 格式的字串。MySQL 在這裡也允許寬鬆語法,儘管已棄用:任何標點符號都可以用作日期部分或時間部分之間的分隔符。例如,'2012-12-31 11:30:45''2012^12^31 11+30+45''2012/12/31 11*30*45''2012@12@31 11^30^45' 是等效的。在此類值中使用除破折號 (-) 作為日期部分和冒號 (:) 作為時間部分以外的任何字元作為分隔符會引發警告,如下所示

    mysql> SELECT TIMESTAMP'2012^12^31 11*30*45';
    +--------------------------------+
    | TIMESTAMP'2012^12^31 11*30*45' |
    +--------------------------------+
    | 2012-12-31 11:30:45            |
    +--------------------------------+
    1 row in set, 1 warning (0.00 sec)
    
    mysql> SHOW WARNINGS\G
    *************************** 1. row ***************************
      Level: Warning
       Code: 4095
    Message: Delimiter '^' in position 4 in datetime value '2012^12^31 11*30*45' at
    row 1 is deprecated. Prefer the standard '-'. 
    1 row in set (0.00 sec)

    日期和時間部分與小數秒部分之間唯一識別的分隔符是小數點。

    日期和時間部分可以用 T 而不是空格分隔。例如,'2012-12-31 11:30:45' '2012-12-31T11:30:45' 是等效的。

    先前,MySQL 支援日期和時間值中任意數量的開頭和結尾空白字元,以及 DATETIMETIMESTAMP 值的日期和時間部分之間。在 MySQL 9.0 中,此行為已棄用,並且存在多餘的空白字元會觸發警告,如下所示

    mysql> SELECT TIMESTAMP'2012-12-31   11-30-45';
    +----------------------------------+
    | TIMESTAMP'2012-12-31   11-30-45' |
    +----------------------------------+
    | 2012-12-31 11:30:45              |
    +----------------------------------+
    1 row in set, 1 warning (0.00 sec)
    
    mysql> SHOW WARNINGS\G
    *************************** 1. row ***************************
      Level: Warning
       Code: 4096
    Message: Delimiter ' ' in position 11 in datetime value '2012-12-31   11-30-45'
    at row 1 is superfluous and is deprecated. Please remove. 
    1 row in set (0.00 sec)

    當使用空格字元以外的空白字元時,也會引發警告,如下所示

    mysql> SELECT TIMESTAMP'2021-06-06
        '> 11:15:25';
    +--------------------------------+
    | TIMESTAMP'2021-06-06
     11:15:25'                       |
    +--------------------------------+
    | 2021-06-06 11:15:25            |
    +--------------------------------+
    1 row in set, 1 warning (0.00 sec)
    
    mysql> SHOW WARNINGS\G
    *************************** 1. row ***************************
      Level: Warning
       Code: 4095
    Message: Delimiter '\n' in position 10 in datetime value '2021-06-06
    11:15:25' at row 1 is deprecated. Prefer the standard ' '.
    1 row in set (0.00 sec)

    每個時間值僅會引發一個此類警告,即使分隔符、空白或兩者都可能存在多個問題,如下面一系列陳述式所示

    mysql> SELECT TIMESTAMP'2012!-12-31  11:30:45';
    +----------------------------------+
    | TIMESTAMP'2012!-12-31  11:30:45' |
    +----------------------------------+
    | 2012-12-31 11:30:45              |
    +----------------------------------+
    1 row in set, 1 warning (0.00 sec)
    
    mysql> SHOW WARNINGS\G
    *************************** 1. row ***************************
      Level: Warning
       Code: 4095
    Message: Delimiter '!' in position 4 in datetime value '2012!-12-31  11:30:45'
    at row 1 is deprecated. Prefer the standard '-'. 
    1 row in set (0.00 sec)
    
    mysql> SELECT TIMESTAMP'2012-12-31  11:30:45';
    +---------------------------------+
    | TIMESTAMP'2012-12-31  11:30:45' |
    +---------------------------------+
    | 2012-12-31 11:30:45             |
    +---------------------------------+
    1 row in set, 1 warning (0.00 sec)
    
    mysql> SHOW WARNINGS\G
    *************************** 1. row ***************************
      Level: Warning
       Code: 4096
    Message: Delimiter ' ' in position 11 in datetime value '2012-12-31  11:30:45'
    at row 1 is superfluous and is deprecated. Please remove. 
    1 row in set (0.00 sec)
    
    mysql> SELECT TIMESTAMP'2012-12-31 11:30:45';
    +--------------------------------+
    | TIMESTAMP'2012-12-31 11:30:45' |
    +--------------------------------+
    | 2012-12-31 11:30:45            |
    +--------------------------------+
    1 row in set (0.00 sec)
  • 作為沒有分隔符的 'YYYYMMDDhhmmss''YYMMDDhhmmss' 格式的字串,前提是該字串作為日期有意義。例如,'20070523091528''070523091528' 會被解釋為 '2007-05-23 09:15:28',但 '071122129015' 是非法的(它具有無意義的分鐘部分)並變成 '0000-00-00 00:00:00'

  • YYYYMMDDhhmmssYYMMDDhhmmss 格式的數字表示,前提是該數字作為日期有意義。例如,19830905132800830905132800 會被解讀為 '1983-09-05 13:28:00'

DATETIMETIMESTAMP 值可以包含尾隨的小數秒部分,精度最高可達微秒(6 位數)。小數部分應始終使用小數點與時間的其餘部分分隔;不認可其他小數秒分隔符。有關 MySQL 中小數秒支援的資訊,請參閱 第 13.2.6 節,「時間值中的小數秒」

包含兩位數年份值的日期具有歧義,因為世紀未知。MySQL 使用以下規則解釋兩位數年份值

  • 範圍在 70-99 的年份值會變成 1970-1999

  • 範圍在 00-69 的年份值會變成 2000-2069

另請參閱 第 13.2.9 節,「日期中的 2 位數年份」

對於指定為包含日期部分分隔符的字串值,小於 10 的月份或日期值不必指定為兩位數。'2015-6-9''2015-06-09' 相同。同樣地,對於指定為包含時間部分分隔符的字串值,小於 10 的小時、分鐘或秒鐘值不必指定為兩位數。'2015-10-30 1:2:3''2015-10-30 01:02:03' 相同。

指定為數字的值應為 6 位、8 位、12 位或 14 位長。如果數字為 8 位或 14 位長,則假定為 YYYYMMDDYYYYMMDDhhmmss 格式,並且年份由前 4 位數字給出。如果數字為 6 位或 12 位長,則假定為 YYMMDDYYMMDDhhmmss 格式,並且年份由前 2 位數字給出。長度不符合這些條件的數字會被解釋為在開頭用零填充到最接近的長度。

指定為無分隔符的字串的值會根據其長度進行解釋。對於長度為 8 或 14 個字元的字串,假定年份由前 4 個字元給出。否則,假定年份由前 2 個字元給出。會從左到右解釋字串,以找到年份、月份、日期、小時、分鐘和秒鐘值,以盡可能多的部分存在於字串中。這表示您不應使用少於 6 個字元的字串。例如,如果您指定 '9903',認為它代表 1999 年 3 月,則 MySQL 會將其轉換為日期值。發生這種情況的原因是年份和月份值為 9903,但日期部分完全遺失。但是,您可以明確指定零值來表示遺失的月份或日期部分。例如,若要插入值 '1999-03-00',請使用 '990300'

MySQL 辨識下列格式的 TIME

  • 'D hh:mm:ss' 格式的字串表示。您也可以使用下列其中一種寬鬆語法:'hh:mm:ss''hh:mm''D hh:mm''D hh''ss'。這裡 D 代表天數,其值範圍為 0 到 34。

  • 'hhmmss' 格式的無分隔符字串表示,前提是它作為時間有意義。例如,'101112' 會被理解為 '10:11:12',但 '109712' 是不合法的(它具有無意義的分鐘部分)並會變成 '00:00:00'

  • hhmmss 格式的數字表示,前提是它作為時間有意義。例如,101112 會被理解為 '10:11:12'。下列替代格式也可以被理解:ssmmsshhmmss

尾隨的小數秒部分可以在 'D hh:mm:ss.fraction''hh:mm:ss.fraction''hhmmss.fraction'hhmmss.fraction 時間格式中識別,其中 fraction 是精度最高可達微秒(6 位數)的小數部分。小數部分應始終使用小數點與時間的其餘部分分隔;不認可其他小數秒分隔符。有關 MySQL 中小數秒支援的資訊,請參閱 第 13.2.6 節,「時間值中的小數秒」

對於指定為包含時間部分分隔符的字串的 TIME 值,小於 10 的小時、分鐘或秒鐘值不必指定為兩位數。'8:3:2''08:03:02' 相同。

TIMESTAMPDATETIME 值插入表格時,您可以指定時區偏移量。偏移量會附加至 datetime 文字的時間部分,中間沒有空格,並且使用設定 time_zone 系統變數時使用的相同格式,但有下列例外

  • 對於小於 10 的小時值,必須加上前導零。

  • 會拒絕值 '-00:00'

  • 時區名稱,例如 'EET''Asia/Shanghai' 無法使用;在此內容中也不能使用 'SYSTEM'

插入的值的月份部分、日期部分或兩者都不能為零。無論伺服器 SQL 模式設定為何,都會強制執行此規則。

此範例說明如何使用不同的 time_zone 設定,將包含時區偏移量的 datetime 值插入 TIMESTAMPDATETIME 資料行中,然後進行擷取

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 |
+---------------------+---------------------+

選取 datetime 值時不會顯示偏移量,即使插入時使用了偏移量也是如此。

支援的偏移量值範圍為 -13:59+14:00(含)。

包含時區偏移量的 datetime 文字會被準備好的陳述式接受為參數值。