我目前正在研究在不同时区运行的客户端和服务器的MySQL日期和时间的行为。我正在编写测试脚本,以便测试当我在某些时区使用客户端和服务器运行时发生了什么,并且作为该工作的一部分,我需要能够控制会话时区。我在将时区设置为我的系统当前默认的同一时区时遇到问题,因此它的行为完全相同。
我想设置mysql SESSION time_zone变量集,以便以与将time_zone变量保留为默认SYSTEM值时相同的方式解释日期。当我手动将time_zone设置为Europe / London时,我希望UNIX_TIMESTAMP继续以与time_zone设置为SYSTEM时相同的方式运行,因为我的mysql system_time_zone设置为在伦敦(GMT夏令时或GMT标准)时间)。相反,我发现UNIX_TIMESTAMP函数返回不同的值,具体取决于time_zone是否设置为' SYSTEM'或者'欧洲/伦敦',如您所见: -
在英国夏令时将日期设置为8月25日,并重新启动MySQL服务器,以便使用system_time_zone =' GMT Summer Time'你可以看到当time_zone是SYSTEM(即GMT夏令时)并且设置为Europe / London时,UNIX_TIMESTAMP函数返回不同的值: -
$ date; mysql --protocol=TCP -uroot -proot mysql -e "show variables LIKE 'system_time_zone'; SET SESSION time_zone = 'SYSTEM'; SELECT @@SESSION.time_zone; select NOW(); select UNIX_TIMESTAMP('1970-01-01 12:00:00');SET SESSION time_zone = 'Europe/London'; SELECT @@SESSION.time_zone; select NOW(); select UNIX_TIMESTAMP('1970-01-01 12:00:00');";
25 Aug 2015 09:12:20
+------------------+-----------------+
| Variable_name | Value |
+------------------+-----------------+
| system_time_zone | GMT Summer Time |
+------------------+-----------------+
+---------------------+
| @@SESSION.time_zone |
+---------------------+
| SYSTEM |
+---------------------+
+---------------------+
| NOW() |
+---------------------+
| 2015-08-25 09:12:21 |
+---------------------+
+---------------------------------------+
| UNIX_TIMESTAMP('1970-01-01 12:00:00') |
+---------------------------------------+
| 43200 |
+---------------------------------------+
+---------------------+
| @@SESSION.time_zone |
+---------------------+
| Europe/London |
+---------------------+
+---------------------+
| NOW() |
+---------------------+
| 2015-08-25 09:12:21 |
+---------------------+
+---------------------------------------+
| UNIX_TIMESTAMP('1970-01-01 12:00:00') |
+---------------------------------------+
| 39600 |
+---------------------------------------+
MyPc
$
将英国冬季时间设置为12月24日,并重新启动mysql服务器,以便使用system_time_zone =' GMT标准时间'我仍然得到相同的结果,因此system_time_zone是在夏天还是标准时间似乎没有什么区别: -
$ date; mysql --protocol=TCP -uroot -proot mysql -e "show variables LIKE 'system_time_zone'; SET SESSION time_zone = 'SYSTEM'; SELECT @@SESSION.time_zone; select NOW(); select UNIX_TIMESTAMP('1970-01-01 12:00:00');SET SESSION time_zone = 'Europe/London'; SELECT @@SESSION.time_zone; select NOW(); select UNIX_TIMESTAMP('1970-01-01 12:00:00');";
25 Dec 2015 09:14:13
+------------------+-------------------+
| Variable_name | Value |
+------------------+-------------------+
| system_time_zone | GMT Standard Time |
+------------------+-------------------+
+---------------------+
| @@SESSION.time_zone |
+---------------------+
| SYSTEM |
+---------------------+
+---------------------+
| NOW() |
+---------------------+
| 2015-12-25 09:14:14 |
+---------------------+
+---------------------------------------+
| UNIX_TIMESTAMP('1970-01-01 12:00:00') |
+---------------------------------------+
| 43200 |
+---------------------------------------+
+---------------------+
| @@SESSION.time_zone |
+---------------------+
| Europe/London |
+---------------------+
+---------------------+
| NOW() |
+---------------------+
| 2015-12-25 09:14:14 |
+---------------------+
+---------------------------------------+
| UNIX_TIMESTAMP('1970-01-01 12:00:00') |
+---------------------------------------+
| 39600 |
+---------------------------------------+
MyPc
$
我可以从cygwin TZ变量中看到我的Windows时区设置为欧洲/伦敦: -
MyPc
$ echo $TZ
Europe/London
MyPc
$
我的问题是: -
更新
我想我可能已回答了我自己的问题。我在1971年10月31日之前发现GMT和UTC NOT 相同,你可以看到: -
http://www.timeanddate.com/time/change/uk/london?year=1970
http://www.timeanddate.com/time/change/uk/london?year=1971
(尝试上述1972年和1973年的链接)
这是因为BST在1971年夏天并不存在,所以在那个夏天GMT比UTC早一个小时,然后在1971年10月31日,时钟第一次回归,GMT与之同步UTC。
因此,如果我像上面那样进行相同的测试,但是使用1973作为年份,那么我获得了与Unix时间戳相同的值(如预期的那样)。这必须意味着当我离开时区时,系统MySQL将日期解释为UTC日期,因此给出12 * 3600 = 43200但是当我将time_zone设置为欧洲/伦敦时,它认为时间意味着英国GMT在冬天1970年是UTC的一小时,因此1970年1月1日中午是11:00 UTC = 11 * 3600 = 39600,如下所示: -
$ date; mysql --protocol=TCP -uroot -proot mysql -e "show variables LIKE 'system_time_zone'; SET SESSION time_zone = 'SYSTEM'; SELECT @@SESSION.time_zone; select NOW(); select UNIX_TIMESTAMP('1973-01-01 12:00:00');SET SESSION time_zone = 'Europe/London'; SELECT @@SESSION.time_zone; select NOW(); select UNIX_TIMESTAMP('1973-01-01 12:00:00');";
25 Aug 2015 12:33:36
+------------------+-----------------+
| Variable_name | Value |
+------------------+-----------------+
| system_time_zone | GMT Summer Time |
+------------------+-----------------+
+---------------------+
| @@SESSION.time_zone |
+---------------------+
| SYSTEM |
+---------------------+
+---------------------+
| NOW() |
+---------------------+
| 2015-08-25 12:33:37 |
+---------------------+
+---------------------------------------+
| UNIX_TIMESTAMP('1973-01-01 12:00:00') |
+---------------------------------------+
| 94737600 |
+---------------------------------------+
+---------------------+
| @@SESSION.time_zone |
+---------------------+
| Europe/London |
+---------------------+
+---------------------+
| NOW() |
+---------------------+
| 2015-08-25 12:33:37 |
+---------------------+
+---------------------------------------+
| UNIX_TIMESTAMP('1973-01-01 12:00:00') |
+---------------------------------------+
| 94737600 |
+---------------------------------------+
MyPc
$
为了避免这个问题,我将从现在开始使用 1973之后的日期进行所有必须测试,并且只是怜悯那些必须在MySQL中处理1973年之前的日期的人。如果这是一个MySQL错误,我不会感到惊讶,因为看起来GMT的系统时区应该完全映射到欧洲/伦敦的SESSION时区,但不是。