如何设置MySQL的时区?

436

在一个服务器上,当我运行以下命令时:

mysql> select now();
+---------------------+
| now()               |
+---------------------+
| 2009-05-30 16:54:29 |
+---------------------+
1 row in set (0.00 sec)

在另一台服务器上:

mysql> select now();
+---------------------+
| now()               |
+---------------------+
| 2009-05-30 20:01:43 |
+---------------------+
1 row in set (0.00 sec)

3
这里不仅存在时区差异,还存在一个不容忽视的时间漂移问题:“与您的数据库管理员谈论 'ntp' - 看看哪种方法适合您!” - colm.anseo
5
放心,这可能只是运行查询时出现的差异。 - HosseyNJF
8
@HosseyNJF 比7分钟快?比较之间有咖啡休息吗? - colm.anseo
"system_time_zone" - "当服务器开始执行时,它会从机器默认设置中继承一个时区设置。" 要更改 "system_time_zone":使用 sudo dpkg-reconfigure tzdata 并使用 sudo service mysql restart 重新启动mysql。 - Avatar
23个回答

660

我认为这可能会有用:

MySQL中可能设置时区的三个位置:

在文件“my.cnf”中的[mysqld]部分

default-time-zone='+00:00'

@@global.time_zone 变量

要查看其设置的值:

SELECT @@global.time_zone;

要为它设置一个值,请使用以下任一方式:

SET GLOBAL time_zone = '+8:00';
SET GLOBAL time_zone = 'Europe/Helsinki';
SET @@global.time_zone = '+00:00';

使用类似于“Europe/Helsinki”这样的命名时区意味着您必须正确填充时区表。

请记住,+02:00是偏移量。Europe/Berlin是一个时区(具有两个偏移量),而CEST是对应于特定偏移量的时钟时间。

@@session.time_zone 变量

SELECT @@session.time_zone;

使用以下任意一种方法进行设置:

SET time_zone = 'Europe/Helsinki';
SET time_zone = "+00:00";
SET @@session.time_zone = "+00:00";

两者可能会返回SYSTEM,这意味着它们使用在my.cnf文件中设置的时区。

为了使时区名称起作用,您必须设置时区信息表并填充其内容: http://dev.mysql.com/doc/refman/5.1/en/time-zone-support.html。我还在这个答案中介绍了如何填充这些表。

要获取当前时区偏移量,可以使用TIME

SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP);

如果你的时区是+2:00,它将返回02:00:00。

获取当前UNIX时间戳:

SELECT UNIX_TIMESTAMP();
SELECT UNIX_TIMESTAMP(NOW());

将时间戳列作为UNIX时间戳获取

SELECT UNIX_TIMESTAMP(`timestamp`) FROM `table_name`

将UTC日期时间列转换为UNIX时间戳

SELECT UNIX_TIMESTAMP(CONVERT_TZ(`utc_datetime`, '+00:00', @@session.time_zone)) FROM `table_name`

注意: 更改时区不会更改存储的日期时间或时间戳,但对现有的时间戳列将显示不同的日期时间,因为它们在内部存储为UTC时间戳,在当前MySQL时区外部显示。

我在这里制作了一个备忘单: MySQL是否应该将其时区设置为UTC?


6
+00:00 并不是一个时区,而是一个时间偏移量。关于夏令时的问题呢?它是全年保持在 +0 吗? - mpen
2
@Mark 我不确定,文档说当设置 time_zone="+00:00" 时,你是在使用相对于UTC的偏移量来设置时区,考虑到设定值从不改变且UTC不遵循夏令时,我可以假设它全年保持不变。 - Timo Huovinen
1
@TimoHuovinen 对不起,我的意思是 +00:00 看起来 像一个偏移量,所以 MySQL 选择使用它来表示 UTC,而不是直接使用字符串 "UTC" 本身,这有点奇怪。谢谢你的信息。 - mpen
1
我有Mac,正在使用vi ;-) - János
6
在Win7中,MySQL设置文件的路径为 C:\ProgramData\MySQL\MySQL Server x.x\my.ini - dev4life
显示剩余14条评论

113

对于仍然遇到这个问题的任何人:

value="jdbc:mysql://localhost:3306/dbname?serverTimezone=UTC"

对我有用。只需在末尾添加?serverTimezone=UTC


1
如果我的时区是UTC+7,我该如何在连接字符串中指定它?我尝试添加"?serverTimezone=UTC+7",但它不起作用。 - Chiến Nghê
4
问题不是关于JDBC,而是关于MySQL本身。 - Luiz
3
你应该使用 Asia/Ho_Chi_Minh 代替 UTC。顺便提一下,这个问题是关于更改 MySQL 时区的。所以请看看 @Timo 的答案。如果你在使用 MySQL docker 时遇到问题,可以添加 TZ 环境变量,这样应该就能解决了。 - Liem Le
5
这只是告诉JDBC服务器所在的时区,它并不会改变时区。要设置会话时区,请查看使用 SET time_zone=... 的答案。 - Nikola Mihajlović
1
最简单的解决方案 - Ahmet Firat Keler

75

当你可以配置MySQL或PHP的时区服务器:

请记住:

  1. 更改时区系统。例如,对于Ubuntu:

$ sudo dpkg-reconfigure tzdata
  • 重新启动服务器,或者您可以重启Apache 2和MySQL:

  • /etc/init.d/mysql restart
    

    3
    也许这种方法可能不是正确的。考虑一下,如果你有一个使用UTC时间的服务器,但你的应用程序向UTC -0600的国家提供数据,那么调整MySQL的时区可能会更好。 - ivanleoncz
    2
    特别是如果您在涵盖多个时区的领域工作。 - Alexis Wilke

    65

    要将它设置为当前会话,请执行以下操作:

    SET time_zone = timezonename;
    

    17
    查询当前会话的时区设置:SELECT @@session.time_zone; - James Skidmore
    1
    我正在尝试修复我的系统中的一些错误,我需要将我的时区设置为UTC而不是GMT。您知道如果我将其设置为“-0:00”或“+00:00”,这是UTC注释还是GMT注释吗?我似乎找不到这个特定的信息。干杯! - rafa.ferreira
    @Castanho,我相信两者都可以正常工作。请查看此问题的解释:http://stackoverflow.com/questions/3466630/mysql-default-time-format-utc-or-gmt - James Skidmore
    时区的值可以与在PHP中设置的值相同,例如 SET time_zone = 'America/Boise'。感谢您的回答,James Skidmore! - Adam Fowler
    1
    @the_nuts 是的,在服务器重新启动期间,SET time_zone = 'UTC'; 设置会丢失。 - Timo Huovinen
    显示剩余2条评论

    58

    只需在您的MySQL服务器上运行以下命令:

    SET GLOBAL time_zone = '+8:00';
    

    +8:00 将是您的时区。


    21
    请注意,这只是暂时的,直到您重新启动MySQL。 - rubo77
    连接到数据库时很少有超级用户权限。按照其他答案所述设置@@session.time_zone是更好的选择。 - colm.anseo
    2
    一旦夏令时开始,这将变得不准确,因为您会从 +8:00 转换到 +9:00(适用于使用夏令时的时区)。 - PromInc

    21

    这对我在印度的位置有用:

    SET GLOBAL time_zone = "Asia/Calcutta";
    SET time_zone = "+05:30";
    SET @@session.time_zone = "+05:30";
    

    你需要将此作为查询在MySQL上运行,或者在my.conf下编写以下语法 default-time-zone = '+05:30'。 - Swapnil Bijwe
    重新启动服务器后,我是否需要重新运行代码? - AdDev

    19

    这是一个10年前的问题,但无论如何,以下是对我有用的方法。我正在使用MySQL 8.0与Hibernate 5和SpringBoot 4。

    我尝试了上面被接受的答案,但对我没有用,对我有用的是这个:

    db.url=jdbc:mysql://localhost:3306/testdb?useSSL=false&serverTimezone=Europe/Warsaw
    

    如果这篇文章对您有所帮助,请不要忘记点赞:D


    16

    请注意,有时候“国家/地区”并不起作用... 这个问题与操作系统、MySQL版本和硬件无关 - 我从FreeBSD 4和2003年的Slackware Linux开始遇到了这个问题,一直持续至今。涉及的MySQL版本从3到最新的源代码主干都有。虽然很奇怪,但确实存在。例如:

    root@Ubuntu# ls -la /usr/share/zoneinfo/US
    total 8
    
    drwxr-xr-x  2 root root 4096 Apr 10  2013 .
    drwxr-xr-x 22 root root 4096 Apr 10  2013 ..
    lrwxrwxrwx  1 root root   18 Jul  8 22:33 Alaska -> ../SystemV/YST9YDT
    lrwxrwxrwx  1 root root   21 Jul  8 22:33 Aleutian -> ../posix/America/Adak
    lrwxrwxrwx  1 root root   15 Jul  8 22:33 Arizona -> ../SystemV/MST7
    lrwxrwxrwx  1 root root   18 Jul  8 22:33 Central -> ../SystemV/CST6CDT
    lrwxrwxrwx  1 root root   18 Jul  8 22:33 Eastern -> ../SystemV/EST5EDT
    lrwxrwxrwx  1 root root   37 Jul  8 22:33 East-Indiana -> ../posix/America/Indiana/Indianapolis
    lrwxrwxrwx  1 root root   19 Jul  8 22:33 Hawaii -> ../Pacific/Honolulu
    lrwxrwxrwx  1 root root   24 Jul  8 22:33 Indiana-Starke -> ../posix/America/Knox_IN
    lrwxrwxrwx  1 root root   24 Jul  8 22:33 Michigan -> ../posix/America/Detroit
    lrwxrwxrwx  1 root root   18 Jul  8 22:33 Mountain -> ../SystemV/MST7MDT
    lrwxrwxrwx  1 root root   18 Jul  8 22:33 Pacific -> ../SystemV/PST8PDT
    lrwxrwxrwx  1 root root   18 Jul  8 22:33 Pacific-New -> ../SystemV/PST8PDT
    lrwxrwxrwx  1 root root   20 Jul  8 22:33 Samoa -> ../Pacific/Pago_Pago
    root@Ubuntu#
    

    而这样的陈述应该是有效的:

    SET time_zone='US/Eastern';
    

    但是你遇到了这个问题:

    错误代码: 1298. 未知或错误的时区: 'EUS/Eastern'

    查看您时区信息目录中的子文件夹,找到符号链接的实际文件名,例如在本例中为 EST5EDT。然后尝试使用以下语句:

    SET time_zone='EST5EDT';
    

    实际上,它正在按照预期工作! :) 记住这个技巧; 我没有看到它在 MySQL 手册和官方文档中有记录。但是阅读相应的文档是必须的: MySQL 5.5时区官方文档 - 别忘了像这样加载时区数据到你的服务器上(以 root 用户身份运行!):

    mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql
    

    技巧一 - 必须在MySQL的root用户下执行。即使从具有MySQL数据库完全访问权限的用户进行,它也可能失败或产生无效结果 - 我亲眼见过这个故障。


    请告诉我您的uname -a和更多细节 - 在Ubuntu桌面和服务器上有一些工作案例。 - Alexey Vesnin
    你是一个英雄。 - aspiringsoftwaredev

    13

    8

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接