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个不同的时区的缩写:
看到system_time_zone: CST
和4种解释,我一脸懵逼。
夏令时的开始时间与结束时间,以2020年为例:
2020年美国夏令时将于2020年3月8日凌晨2点开始,至2020年11月1日凌晨2点夏令时结束。
美国夏时制的实行与否,完全由各州、各县自行决定,不由联邦政府统一规定。目前美国绝大部分地区实行夏令时,美国不实行夏令时地区包括:
- 亚利桑那州的绝大部分地区(除东北一小区块);
- 夏威夷州;
- 波多黎各和维京群岛;
- 美属萨摩亚、关岛和北马里亚纳群岛。
美国和加拿大原本于每年10月的最后一个星期日凌晨2时起实施冬令时间;4月的第一个星期日凌晨2时起,恢复夏令时间。
但是根据美国国会最新通过的能源法案,为加强日光节约,自2007年起延长夏令时间,从每年3月的第二个星期日开始,至每年11月的第一个星期日结束,因此,冬令时间将缩短约一个月。之所以安排在周日,是为了便于生活的调整不至于受到较大的影响。
——来自百度百科
美国时间与中国时间时差(夏令时):
美国的时区以及所属区域:
将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、时间设置为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 转换格式,得到:
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()不包含夏令时。
将主机的时区设置为美国太平洋时区 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为时区名称,如地理位置在西八区的美国洛杉矶。
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
MySQL Server Time Zone Support[DB|OL]. https://dev.mysql.com/doc/refman/5.7/en/time-zone-support.html ↩︎
mysql_tzinfo_to_sql — Load the Time Zone Tables[DB|OL]. https://dev.mysql.com/doc/refman/5.7/en/mysql-tzinfo-to-sql.html ↩︎
MySQL::时区描述表[DB|OL]. https://dev.mysql.com/downloads/timezones.html ↩︎