$ SELECT @@global.time_zone, @@session.time_zone, @@system_time_zone
@@global.time_zone: SYSTEM
@@session.time_zone: SYSTEM
@@system_time_zone: +08
set time_zone="+00:00"
select now()
由于Datetime是以字符串存储的,其值在写入时已经确定,只支持2020-02-02 20:20:20
的写入。
所以,改变connection或者server的时区,不会更新已有的数据。
此外,如果对datetime作匹配,不会应用时区信息:
$ SELECT id,create_time FROM test_tab WHERE create_time="2023-03-13 11:51:00" \G'
*************************** 1. row ***************************
id: 160482
create_time: 2023-03-13 11:51:00
$ SELECT id,create_time FROM test_tab WHERE create_time="2023-03-13 11:51:00+08:00" \G'
*************************** 1. row ***************************
id: 160482
create_time: 2023-03-13 11:51:00
这说明Datetime和普通的字符串匹配不一样,mysql会把字符串先转成时区再进行操作
改变时区,并不会改变已有的数据。
我们可以将mysql对于Datetime类型的操作,可以理解为以下步骤:
将时间标准化,移除多余的字符串
Beginning with MySQL 8.0.19, you can specify a time zone offset when inserting TIMESTAMP and DATETIME values into a table. The offset is appended to the time part of a datetime literal, with no intravening spaces, and uses the same format used for setting the time_zone system variable, with the following exceptions:
再对时间进行存储或比较
https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_adddate
$ SET time_zone="+00:00"
$ SELECT unix_timestamp("2023-03-13 11:51:00")\G
1678708260
$ SET time_zone="+08:00"
$ SELECT unix_timestamp("2023-03-13 11:51:00")\G
1678679460
1678679460s - 1678708260s = 28800s = 8h
$ select unix_timestamp("2")
0.000000
$ select unix_timestamp("2022")
0.000000
$ select unix_timestamp("2022-02-??")
0.000000
$ select unix_timestamp("2022-02-02")
1643731200
# 不合法的日期,比如12-32日,也返回0
$ select unix_timestamp("2022-12-32")
0
$ SELECT unix_timestamp("1900-01-01")
0
$ SELECT unix_timestamp("1970-01-01")
0
$ SELECT unix_timestamp("1970-01-02")
59400
注意,nodejs中的getTime
会返回负数的时间戳
> new Date("1970-01-01").getTime()
0
> new Date("1900-01-01").getTime()
-2208988800000
$ SELECT DATEDIFF("1901-01-01 23:59:59","1900-12-31 23:59:59")
1
$ SELECT DATEDIFF("1901-01-01 23:59:59","1900-12-32 23:59:59")
NULL
SELECT TIME'20:20:20'
SELECT DATE'2020-02-02'
SELECT TIMESTAMP'2020-02-02 20:20:20'
DATE: 1000-01-01 to 9999-12-31
DATETIME: 1000-01-01 00:00:00 to 9999-12-31 23:59:59
TIMESTAMP: 1970-01-01 00:00:01 to 2038-01-19 03:14:07
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’.
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:ss’ format. The supported range is ‘1000-01-01 00:00:00’ to ‘9999-12-31 23:59:59’.
TIMESTAMP has a range of ‘1970-01-01 00:00:01’ UTC to ‘2038-01-19 03:14:07’ UTC.
https://dev.mysql.com/doc/refman/8.0/en/datetime.html
TIMESTAMP类型自动转换为UTC时间存储,查询时再转换为当前时区。
但是对于DATETIME类型没有这个转换,仅仅是以标准化后的字符串形式存储。
MySQL converts TIMESTAMP values from the current time zone to UTC for storage, and back from UTC to the current time zone for retrieval.