第 22.1 节:以特定时区检索当前日期和时间
SELECT NOW();
SET time_zone = 'Asia/Kolkata';
SELECT NOW();
SET time_zone = 'UTC';
SELECT NOW();
这首先获取本地时间的 NOW(),然后是印度标准时间,最后是 UTC 时间。
第 22.2 节:将存储的 DATE 或 DATETIME 值转换为其他时区
如果你有一个存储的 DATE 或 DATETIME 值(在表的某列中),它是相对于某个时区存储的,但在 MySQL 中时区不会与值一起存储。因此,如果你想将其转换为另一个时区,可以这样做,但你必须知道原始时区。使用 CONVERT_TZ() 进行转换。以下示例显示加利福尼亚州售出的行,时间为当地时区:
SELECT CONVERT_TZ(date_sold, 'UTC', 'America/Los_Angeles') AS date_sold_local
FROM sales
WHERE state_sold = 'CA';
第 22.3 节:以特定时区检索存储的 TIMESTAMP 值
这非常简单。所有 TIMESTAMP 值都以 UTC 存储,并且在呈现时始终转换为当前的 time_zone 设置。
SET SESSION time_zone = 'America/Los_Angeles';
SELECT timestamp_sold FROM sales WHERE state_sold = 'CA';
为什么会这样?TIMESTAMP 值基于古老的 time_t 数据类型。这些 UNIX 时间戳存储为自 1970-01-01 00:00:00 UTC 以来的秒数。
注意:TIMESTAMP 值以 UTC 存储。DATE 和 DATETIME 值以存储它们时的任何本地时区存储。
第 22.4 节:我的服务器的本地时区设置是什么?
每个服务器都有一个默认的全局 time_zone 设置,由服务器机器的所有者配置。你可以通过以下方式找到当前的时区设置:
SELECT @@global.time_zone;
不幸的是,这通常返回值 SYSTEM,意味着 MySQL 时间由服务器操作系统的时区设置控制。
以下查询序列(是的,这是一个技巧)返回服务器时区设置与 UTC 之间的偏移量(以分钟为单位):
CREATE TEMPORARY TABLE times (dt DATETIME, ts TIMESTAMP);
SET time_zone = 'UTC';
INSERT INTO times VALUES(NOW(), NOW());
SET time_zone = 'SYSTEM';
SELECT dt, ts, TIMESTAMPDIFF(MINUTE, dt, ts) AS offset FROM times;
DROP TEMPORARY TABLE times;
这是如何工作的?临时表中两种不同数据类型的列是关键。DATETIME 数据类型在表中始终以本地时间存储,而 TIMESTAMP 以 UTC 存储。因此,当 time_zone 设置为 UTC 时执行 INSERT 语句,会存储两个相同的日期/时间值。
然后,当 time_zone 设置为服务器本地时间时执行 SELECT 语句。TIMESTAMP 在 SELECT 语句中总是从存储的 UTC 形式转换为本地时间。DATETIME 则不会。因此,TIMESTAMPDIFF(MINUTE, ...) 操作计算本地时间和 UTC 之间的差异。
第 22.5 节:我的服务器中有哪些 time_zone 值可用?
要获取 MySQL 服务器实例中可用的 time_zone 值列表,请使用以下命令:
SELECT mysql.time_zone_name.name;
通常情况下,这会显示由互联网号码分配局(IANA)的 Paul Eggert 维护的 Zonelnfo 时区列表。全球大约有 600 个时区。
类 Unix 操作系统(Linux 发行版、BSD 发行版和现代 Mac OS 发行版等)会定期接收更新。在操作系统上安装这些更新可使在其上运行的 MySQL 实例跟踪时区和夏令时/标准时间切换的变化。
如果你得到的时区名称列表短得多,说明你的服务器要么配置不完整,要么运行在 Windows 上。以下是给你的服务器管理员安装和维护 Zonelnfo 列表的说明。