Mysql中TimeStamp、DateTime、Date關於時區(TimeZone)的問題

存儲時間的幾種方式

一般情況下:數據庫可以這樣存儲時間:

  • bigint(存毫秒數Long)
    • 存儲時間戳,然後new Date(long date)轉化爲時間
  • DateTime
  • TimeStamp時間戳

閱讀官方文檔

1、DATE, DATETIME, TIMESTAMP三者的區別:

首先說一下三者的不同之處:

The DATE type is used for values with a date part but no time part. MySQL retrieves and displays DATE values in '*YYYY-MM-DD*' format. The supported range is '1000-01-01' to '9999-12-31'.

Date只表示日期,年-月-日,不表示具體的時間

The DATETIME type is used for values that contain both date and time parts. MySQL retrieves and displays DATETIME values in YYYY-MM-DD hh:mm:ssformat. The supported range is '1000-01-01 00:00:00' to '9999-12-31 23:59:59'.

DateTime即表示日期,又表示時間,YYYY-MM-DD hh:mm:ss,它更像是一個·字符串表示

The TIMESTAMP data type is used for values that contain both date and time parts. TIMESTAMP has a range of '1970-01-01 00:00:01' UTC to '2038-01-19 03:14:07' UTC.

TIMESTAMP 和DateTime類似,即表示時間,又表示日期,

A DATETIME or TIMESTAMP value can include a trailing fractional seconds part in up to microseconds (6 digits) precision. In particular, any fractional part in a value inserted into a DATETIME or TIMESTAMP column is stored rather than discarded. With the fractional part included, the format for these values is '*YYYY-MM-DD hh:mm:ss*[.*fraction*]', the range for DATETIME values is '1000-01-01 00:00:00.000000' to '9999-12-31 23:59:59.999999', and the range for TIMESTAMP values is '1970-01-01 00:00:01.000000' to '2038-01-19 03:14:07.999999'. The fractional part should always be separated from the rest of the time by a decimal point; no other fractional seconds delimiter is recognized. For information about fractional seconds support in MySQL, see Section 11.2.6, “Fractional Seconds in Time Values”.

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”。

小數部分應始終與其餘時間用小數點分隔;不能識別其他小數秒分隔符

2、TIMESTAMP 與TimeZone的關係

MySQL converts TIMESTAMP values from the current time zone to UTC for storage, and back from UTC to the current time zone for retrieval. (This does not occur for other types such as DATETIME.)

存儲時,MySQL將TIMESTAMP 值從當前時區轉換爲UTC時間進行存儲,查詢時,將數據從UTC轉換爲檢索的當前時區。(其他類型(如DATETIME)不會發生這種情況。)

By default, the current time zone for each connection is the server’s time. The time zone can be set on a per-connection basis. As long as the time zone setting remains constant, you get back the same value you store.

默認情況下,每個連接的當前時區是服務器的時間。時區可以根據每個連接進行設置。只要時區設置保持不變,就可以得到存儲的相同值。

If you store a TIMESTAMP value, and then change the time zone and retrieve the value, the retrieved value is different from the value you stored. This occurs because the same time zone was not used for conversion in both directions. The current time zone is available as the value of the time_zone system variable. For more information, see Section 5.1.13, “MySQL Server Time Zone Support”.

如果存儲TIMESTAMP 值,然後更改時區並檢索該值,則檢索到的值與存儲的值不同。發生這種情況的原因是沒有使用同一時區在兩個方向上進行轉換。當前時區可用作時區系統變量的值。有關詳細信息,請參閱第5.1.13節“MySQL服務器時區支持”。

3、關於Mysql中TimeZone的簡介:

MySQL Server maintains several time zone settings:

MySQL Server維護幾個時區設置:

  • The system time zone. When the server starts, it attempts to determine the time zone of the host machine automatically and uses it to set the system_time_zone system variable. The value does not change thereafter.

    系統時區。服務器啓動時,它將嘗試自動確定主機的時區,並使用它來設置 system_time_zone系統變量。此後該值不變。

    To explicitly specify the system time zone for MySQL Server at startup, set the TZ environment variable before you start mysqld. If you start the server using mysqld_safe, its --timezone option provides another way to set the system time zone. The permissible values for TZ and --timezone are system dependent. Consult your operating system documentation to see what values are acceptable.

    要在啓動時爲MySQL Server明確指定系統時區,請在啓動mysqldTZ之前設置環境變量。如果使用mysqld_safe啓動服務器,則其 選項提供了另一種設置系統時區的方法。對於允許值和 是取決於系統。請查閱操作系統文檔,以瞭解可以接受的值。 --timezoneTZ--timezone

  • The server current time zone. The global time_zone system variable indicates the time zone the server currently is operating in. The initial time_zone value is 'SYSTEM', which indicates that the server time zone is the same as the system time zone.

    服務器當前時區。全局 time_zone系統變量指示服務器當前正在運行的時區。初始time_zone 值爲'SYSTEM',指示服務器時區與系統時區相同。

  • Per-session time zones. Each client that connects has its own session time zone setting, given by the session time_zone variable. Initially, the session variable takes its value from the global time_zone variable, but the client can change its own time zone with this statement:

    會話時區。每個連接的客戶端都有自己的會話時區設置,由會話 time_zone變量指定。最初,會話變量從全局變量獲取其值time_zone,但是客戶端可以使用以下語句更改其自己的時區:

關鍵就是會話TimeZone,每個客戶端

數據庫默認的時區都是System

在這裏插入圖片描述

4、如何修改timezone的值

timezone 值可以以幾種格式給出,都不區分大小寫:

  • 作爲值'SYSTEM',指示服務器時區與系統時區相同。
  • 作爲表示一個字符串的從表單的UTC偏移 ,帶有前綴+-,例如, +10:00, '-6:00', or +05:30,例如我們是東八區+8:00
    • MySQL 8.0.19之前,該值必須在範圍 '-12:59''+13:00',包容性;
    • MySQL 8.0.19之後,允許範圍爲'-14:00''+14:00',包容性。
  • 作爲命名的時區,例如 'Europe/Helsinki''US/Eastern''MET'。僅當mysql已經創建並填充了數據庫中的時區信息表時,才能使用命名時區 。
-- 設置session時區
SET time_zone = 'Asia/Shanghai';
-- 查詢系統時區和session時區
SELECT @@global.time_zone, @@session.time_zone;
-- 當前session時區
show VARIABLES like '%time_zone%';

5、TimeZone的影響

The session time zone setting affects display and storage of time values that are zone-sensitive. This includes the values displayed by functions such as NOW() or CURTIME(), and values stored in and retrieved from TIMESTAMP columns. Values for TIMESTAMP columns are converted from the session time zone to UTC for storage, and from UTC to the session time zone for retrieval.

會話時區設置會影響對時區敏感的時間值的顯示和存儲。這包括由諸如NOW()或 的函數顯示的值 CURTIME(),以及存儲在TIMESTAMP 列中並從列中檢索的值。TIMESTAMP 列的值從會話時區轉換爲UTC以進行存儲,並從UTC轉換爲會話時區以進行檢索。

The session time zone setting does not affect values displayed by functions such as UTC_TIMESTAMP() or values in DATE, TIME, or DATETIME columns. Nor are values in those data types stored in UTC; the time zone applies for them only when converting from TIMESTAMP values. If you want locale-specific arithmetic for DATE, TIME, or DATETIME values, convert them to UTC, perform the arithmetic, and then convert back.

會話時區設置不會影響 UTC_TIMESTAMP()函數DATETIME,或 DATETIME列中的或值 。這些數據類型中的值也不會像TimeStamp轉換爲UTC存儲;時區僅在從TIMESTAMP值轉換時適用 。如果要針對DATETIMEDATETIME值進行語言環境特定的算術 ,請將其轉換爲UTC,執行該算術,然後再轉換回去。

demo測試

可能上邊的大段文字,你沒有讀懂,那我現在給你舉一個例子:

有一個user表如圖所示:

在這裏插入圖片描述

gmt_create是timestamp類型的

當前會話時區爲+8:00即東八區,查詢所有用戶:

在這裏插入圖片描述

當前session時區爲'+8:00'(北京)

set time_zone=‘+0:00’修改時區,再次查詢發現TimeStamp類型的gmt_create發生了變化。

在這裏插入圖片描述

總結

  • DateTimeDateTime類型不支持時區轉換。
  • TimeStamp列的值從會話時區轉換爲UTC以進行存儲,並從UTC轉換爲會話時區以進行檢索。
    • 可以理解爲它存儲時區,而DateTime不存儲時區。
    • 且從DateTimeTimeStamp的表示範圍上,我們就能看出來DateTime有點字符串的意思,而TimeStamp則不是。

參考資料

https://developer.aliyun.com/article/728315
https://segmentfault.com/a/1190000016426048
https://dev.mysql.com/doc/refman/8.0/en/time-zone-support.html
https://dev.mysql.com/doc/refman/8.0/en/time-zone-support.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章