文章目录
总结
MySQL的timezone值可以多种格式给出,都不区分大小写:1
-
时区偏移量,表示从UTC开始的偏移量
[H]H:MM
,带有前缀+
或-
,例如,+[H]H:MM
,-[H]H:MM
。当小时值小于10,可选择使用前导零;在这种情况下,MySQL在存储和检索时会预先设置前导零,将"-00:00"或"-0:00"转换为"+00:00"。时区偏移必须在"-12:59"到"13:00"的范围内。NOW()不包含夏令时
-
时区名称,例如
'UTC'
,'Asia/Shanghai'
,'America/Los_Angeles'
,'Europe/Helsinki'
,'US/Eastern'
,'MET'
。当且仅当mysql已经创建并填充了数据库中的时区信息表时,才能使用时区名称 。NOW()包含夏令时
-
SYSTEM
,指示服务器时区与主机系统时区相同。取决于MySQL Server所在主机的时间
mysql> show variables like '%time_zone%';
+------------------+--------+
| Variable_name | Value |
+------------------+--------+
| system_time_zone | CST |
| time_zone | -08:00 |——时区偏移量,NOW()不含夏令时
+------------------+--------+
2 rows in set (0.01 sec)
mysql> show variables like '%time_zone%';
+------------------+---------------------+
| Variable_name | Value |
+------------------+---------------------+
| system_time_zone | CST |
| time_zone | America/Los_Angeles |——时区名称,NOW()含夏令时
+------------------+---------------------+
2 rows in set (0.00 sec)
mysql> show variables like '%time_zone%';
+------------------+--------+
| Variable_name | Value |
+------------------+--------+
| system_time_zone | PDT |——PDT太平洋时区,代表城市"洛杉矶"
| time_zone | SYSTEM |——表示MySQL Server时区与主机系统时区相同
+------------------+--------+
2 rows in set (0.01 sec)
下方的实验过程可以忽略。
实验过程
环境
主机:CentOS 7.2
数据库:MySQL 5.7.22
查看MySQL基本信息(MySQL版本、操作系统、主机时区、数据库时区)。
mysql> SELECT @@global.version, @@global.version_compile_os, @@global.system_time_zone, @@global.time_zone, @@session.time_zone\G
*************************** 1. row ***************************
@@global.version: 5.7.22
@@global.version_compile_os: Linux
@@global.system_time_zone: CST
@@global.time_zone: SYSTEM
@@session.time_zone: SYSTEM
1 row in set (0.00 sec)
mysql> show variables like '%time_zone%';
+------------------+--------+
| Variable_name | Value |
+------------------+--------+
| system_time_zone | CST |
| time_zone | SYSTEM |
+------------------+--------+
2 rows in set (0.01 sec)
度娘说CST可以为如下4个不同的时区的缩写:
- 美国中部时间:Central Standard Time (USA) UT-6:00
- 澳大利亚中部时间:Central Standard Time (Australia) UT+9:30
- 中国标准时间:China Standard Time UT+8:00
- 古巴标准时间:Cuba Standard Time UT-4:00
看到system_time_zone: CST
和4种解释,我一脸懵逼。
NOW()会自动计算夏令时吗?
夏令时的开始时间与结束时间,以2020年为例:
2020年美国夏令时将于2020年3月8日凌晨2点开始,至2020年11月1日凌晨2点夏令时结束。
关于美国的夏令时
美国夏时制的实行与否,完全由各州、各县自行决定,不由联邦政府统一规定。目前美国绝大部分地区实行夏令时,美国不实行夏令时地区包括:
- 亚利桑那州的绝大部分地区(除东北一小区块);
- 夏威夷州;
- 波多黎各和维京群岛;
- 美属萨摩亚、关岛和北马里亚纳群岛。
美国和加拿大原本于每年10月的最后一个星期日凌晨2时起实施冬令时间;4月的第一个星期日凌晨2时起,恢复夏令时间。
但是根据美国国会最新通过的能源法案,为加强日光节约,自2007年起延长夏令时间,从每年3月的第二个星期日开始,至每年11月的第一个星期日结束,因此,冬令时间将缩短约一个月。之所以安排在周日,是为了便于生活的调整不至于受到较大的影响。
——来自百度百科
美国时间与中国时间时差(夏令时):
- UTC-5 EST 东部时区:代表城市纽约、华盛顿,与北京相差12小时;
- UTC-6 CST 中部时区:代表城市芝加哥,与北京相差13小时;
- UTC-7 MST 山地时区:代表城市盐湖城,与北京相差14小时;
- UTC-8 PST 太平洋时区:代表城市洛杉矶,与北京相差15小时;
- UTC-9 AKST 阿拉斯加时区:代表城市:费尔班克斯,与北京相差16小时。
美国的时区以及所属区域:
- UTC+10 夏莫罗标准时区
- UTC-11 美属萨摩亚标准时区
- UTC-10 HST 夏威夷-阿留申标准时区
- UTC-9 AKST 阿拉斯加标准时区
- UTC-8 PST 太平洋标准时区
- UTC-7 MST 山地标准时区
- UTC-6 CST 中部标准时区
- UTC-5 EST 东部标准时区
- UTC-4 AST 大西洋标准时区
将MySQL Server时区设置为西八区,NOW()会自动计算夏令时吗?
@@session.time_zone。每个连接的客户端都有自己的会话时区设置,由@@session.time_zone变量指定。最初,session变量从global变量获取其值time_zone,但是客户端可以使用以下语句更改其自己的时区
将MySQL Server的变量@@session.time_zone设置为西八区,并查看NOW()
mysql> SET @@session.time_zone='-08:00';
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @@session.time_zone;
+---------------------+
| @@session.time_zone |
+---------------------+
| -08:00 |
+---------------------+
1 row in set (0.00 sec)
或者直接改MySQL的配置文件my.cnf,然后重启MySQL Server。
[mysqld]
default-time-zone='-08:00'
主机时间
# date +'%Y-%m-%d %H:%M:%S %Z %z'
2020-01-18 23:27:36 CST +0800
主机的时区设置
东八区上海 timedatectl set-timezone Asia/Shanghai
西六区芝加哥timedatectl set-timezone America/Chicago
西八区洛杉矶timedatectl set-timezone America/Los_Angeles
Linux系统时间同步(NTP)要关闭,为了我们人为设置Linux系统时间。
- 关闭
timedatectl set-ntp false
- 开启
timedatectl set-ntp true
主机时区设置为Asia/Shanghai
将主机的时区设置为Asia/Shanghai、时间设置为2020-04-01 00:00:00
MySQL的time_zone设置成时区偏移量’-08:00’,
查看SELECT NOW(), UNIX_TIMESTAMP()
与北京时间相差几个小时?
# timedatectl set-timezone Asia/Shanghai
# date +'%Y-%m-%d %H:%M:%S %Z %z'
2020-04-01 00:05:29 CST +0800
mysql> SET @@session.time_zone='-08:00';
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @@session.time_zone, NOW(), UNIX_TIMESTAMP();
+---------------------+---------------------+------------------+
| @@session.time_zone | NOW() | UNIX_TIMESTAMP() |
+---------------------+---------------------+------------------+
| -08:00 | 2020-03-31 08:05:29 | 1585670729 |
+---------------------+---------------------+------------------+
1 row in set (0.00 sec)
用PHP将时间戳 1585670729 转换格式,得到:
- 2020-03-31 16:05:29 UTC +00:00 UTC
- 2020-03-31 09:05:29 PST -08:00 America/Los_Angeles—— (PHP根据时区名称,自动包含夏令时,而MySQL根据时区偏移量’-08:00’只能转换成’08:05:29’,与PHP得到的结果相差一个小时)
- 2020-04-01 00:05:29 CST +08:00 Asia/Shanghai——(上海洛杉矶相差15小时,即包含夏令时)
<?php
date_default_timezone_set('UTC');
$int = 1585670729;
format($int);
date_default_timezone_set('America/Los_Angeles');
format($int);
date_default_timezone_set('Asia/Shanghai');
format($int);
function format($timestamp)
{
$format = 'Y-m-d H:i:s T P';
echo date($format, $timestamp) . ' ' . date_default_timezone_get() . PHP_EOL;
}
结论
同样的时间戳1585670729,若MySQL的time_zone设置为时区偏移量’-08:00’,则NOW()不包含夏令时。
主机时区设置为America/Los_Angeles
将主机的时区设置为美国太平洋时区 PDT、时间设置为2020-04-01 00:00:00
MySQL的time_zone设置成时区偏移量’-08:00’,
# timedatectl set-timezone America/Los_Angeles
# date +'%Y-%m-%d %H:%M:%S %Z %z'
2020-04-01 00:07:10 PDT -0700
mysql> SET @@session.time_zone='-08:00';
mysql> SELECT @@session.time_zone, NOW(), UNIX_TIMESTAMP();
+---------------------+---------------------+------------------+
| @@session.time_zone | NOW() | UNIX_TIMESTAMP() |
+---------------------+---------------------+------------------+
| -08:00 | 2020-03-31 23:07:10 | 1585724830 |
+---------------------+---------------------+------------------+
1 row in set (0.00 sec)
用PHP将时间戳 1585724830 转换格式,得到:
2020-04-01 07:07:10 UTC +00:00 UTC
2020-04-01 00:07:10 PDT -07:00 America/Los_Angeles
2020-04-01 15:07:10 CST +08:00 Asia/Shanghai——(上海洛杉矶相差15小时,即包含夏令时)
结论
若MySQL的time_zone设置为时区偏移量,如’-08:00’,则NOW()不包含夏令时。
time_zone设置为时区名称
设置time_zone为时区名称,如地理位置在西八区的美国洛杉矶。
mysql> SET @@session.time_zone='America/Los_Angeles';
ERROR 1298 (HY000): Unknown or incorrect time zone: 'America/Los_Angeles'
上方报错的原因是MySQL数据库中的时区信息默认为空。即mysql库下的时区表都是空表。
mysql> use mysql;
Database changed
mysql> SHOW TABLES LIKE "%time%";
+---------------------------+
| Tables_in_mysql (%time%) |
+---------------------------+
| time_zone |
| time_zone_leap_second |
| time_zone_name |
| time_zone_transition |
| time_zone_transition_type |
+---------------------------+
5 rows in set (0.00 sec)
填充时区表
Linux系统的时区文件导入MySQL Server的mysql库。
需要先进入MySQL安装目录的bin目录下,执行mysql_tzinfo_to_sql命令,Linux系统下的时区文件路径作为参数,2
[root@sy-pc bin]# cd /application/mysql/bin
[root@sy-pc bin]# mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
Enter password:
Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it.
如果您的系统没有zoneinfo数据库(例如Windows),则可以使用包含SQL语句的软件包,该软件包可从MySQL开发人员区域下载https://dev.mysql.com/downloads/timezones.html3,然后导入MySQL的mysql库中。
如果您的系统包含zoneinfo文件(例如Linux,FreeBSD,Sun Solaris),请不要使用此软件包。请mysql.time_zone*改用mysql_tzinfo_to_sql实用程序从这些文件中生成表!(否则,可能会导致MySQL与系统上其他应用程序之间在日期时间处理上有所不同。)
设置time_zone为洛杉矶
mysql> SET @@session.time_zone='America/Los_Angeles';
Query OK, 0 rows affected (0.00 sec)
mysql> show variables like '%time_zone%';
+------------------+---------------------+
| Variable_name | Value |
+------------------+---------------------+
| system_time_zone | CST |
| time_zone | America/Los_Angeles |
+------------------+---------------------+
2 rows in set (0.00 sec)
设置主机时区、时间
# timedatectl set-timezone America/Los_Angeles
# date +'%Y-%m-%d %H:%M:%S %Z %z'
2020-04-01 00:00:55 PDT -0700
mysql> SELECT @@session.time_zone, NOW(), UNIX_TIMESTAMP();
+---------------------+---------------------+------------------+
| @@session.time_zone | NOW() | UNIX_TIMESTAMP() |
+---------------------+---------------------+------------------+
| America/Los_Angeles | 2020-04-01 00:00:55 | 1585724455 |
+---------------------+---------------------+------------------+
1 row in set (0.00 sec)
用PHP将时间戳 1585724455 转换格式,得到:
2020-04-01 07:00:55 UTC +00:00 UTC
2020-04-01 00:00:55 PDT -07:00 America/Los_Angeles
2020-04-01 15:00:55 CST +08:00 Asia/Shanghai
此时,我们将time_zone设置成时区偏移量,看看MySQL会不会自动计算夏时令。显然,time_zone为时区偏移量,MySQL不包含夏令时。
mysql> SET @@session.time_zone='-08:00';
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @@session.time_zone, NOW(), UNIX_TIMESTAMP();
+---------------------+---------------------+------------------+
| @@session.time_zone | NOW() | UNIX_TIMESTAMP() |
+---------------------+---------------------+------------------+
| -08:00 | 2020-03-31 23:05:12 | 1585724712 |
+---------------------+---------------------+------------------+
1 row in set (0.00 sec)
结论
若MySQL的time_zone设置为时区名称,则NOW()包含夏令时。
mysql> SELECT
-> CONVERT_TZ('2007-03-11 2:00:00','US/Eastern','US/Central') AS time1,
-> CONVERT_TZ('2007-03-11 3:00:00','US/Eastern','US/Central') AS time2;
+---------------------+---------------------+
| time1 | time2 |
+---------------------+---------------------+
| 2007-03-11 01:00:00 | 2007-03-11 01:00:00 |
+---------------------+---------------------+
1 row in set (0.01 sec)
mysql> SELECT
-> CONVERT_TZ('2020-04-01 00:00:00','Asia/Shanghai', 'America/Los_Angeles') AS 'time1',
-> CONVERT_TZ('2020-01-01 00:00:00','Asia/Shanghai', 'America/Los_Angeles') AS 'time2';
+---------------------+---------------------+
| time1 | time2 |
+---------------------+---------------------+
| 2020-03-31 09:00:00 | 2019-12-31 08:00:00 |
+---------------------+---------------------+
1 row in set (0.00 sec)
遗留问题
上述操作中mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql -p
爆出的Warning是啥意思?
[root@sy-pc bin]# cd /application/mysql/bin
[root@sy-pc bin]# mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql -p
Enter password:
Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it.
Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it.
参考文献
mysql 时区 , 夏令时,冬令时[DB|OL]. https://www.cnblogs.com/zengkefu/p/5611392.html
来源:CSDN
作者:飞蛾逐月
链接:https://blog.csdn.net/zhou16333/article/details/104034854