我正在努力处理 MariaDB 10.3 中的时间值。特别是,我无法理解何时根据配置的时区转换时间值,何时不转换。
CREATE TABLE aoeui (
id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
created DATETIME DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO aoeui () VALUES ();
SELECT *, CURRENT_TIMESTAMP as ts FROM aoeui;
-- Note: I'm on CEST, which is currently +02:00 and the goal of this value
-- is just to be different from that to illustrate the behaviour.
SET TIME_ZONE = '+08:00';
SELECT *, CURRENT_TIMESTAMP as ts FROM aoeui;
DROP TABLE aoeui;
-- reset timezone, so you can re-run the code in the same session
SET TIME_ZONE = 'SYSTEM';
注意:插入和两个查询很容易在一秒钟内运行,因此任何时间戳最多应该在那么短的运行时间之间有所不同,我在这里称它们为相等,尽管这在现实中不是 100% true(和竞争条件)。
注2:两个值
2023-08-15 14:26:47 +0800
和2023-08-15 08:26:47 +0200
描述了同一时间点,只是以两种不同的方式。
在第一个
SELECT
查询中,结果显示同一时间点两次。在第二个查询中,结果两次包含相同的时间点,仅代表不同的时区。但是,第二个查询仅获得正确的 CURRENT_TIMESTAMP
值,从表中检索到的值的表示形式与第一个查询中的相同。
Database changed
MariaDB [tmp]> CREATE TABLE aoeui (
-> id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> created DATETIME DEFAULT CURRENT_TIMESTAMP
-> );
Query OK, 0 rows affected (0.030 sec)
MariaDB [tmp]> INSERT INTO aoeui () VALUES ();
Query OK, 1 row affected (0.004 sec)
MariaDB [tmp]> SELECT *, CURRENT_TIMESTAMP as ts FROM aoeui;
+----+---------------------+---------------------+
| id | created | ts |
+----+---------------------+---------------------+
| 1 | 2023-08-15 08:26:47 | 2023-08-15 08:26:47 |
+----+---------------------+---------------------+
1 row in set (0.001 sec)
MariaDB [tmp]> SET TIME_ZONE = '+08:00';
Query OK, 0 rows affected (0.000 sec)
MariaDB [tmp]> SELECT *, CURRENT_TIMESTAMP as ts FROM aoeui;
+----+---------------------+---------------------+
| id | created | ts |
+----+---------------------+---------------------+
| 1 | 2023-08-15 08:26:47 | 2023-08-15 14:26:47 |
+----+---------------------+---------------------+
1 row in set (0.000 sec)
MariaDB [tmp]> DROP TABLE aoeui;
Query OK, 0 rows affected (0.010 sec)
您可以在第二个查询中看到,时间从
08
更改为 14
,但这只是针对其中一个结果。我本来希望两者都会改变。
MariaDB 不以 TIMESTAMP 类型存储时区。
如果更改 MariaDB 中的 time_zone,后续操作将使用新时间,但现有数据不会更改。
如果您必须使用多个时区,您应该将时间存储为 UTC 时间戳。
CREATE TABLE aoeui (id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
created DATETIME DEFAULT UTC_TIMESTAMP());
要根据您的时区显示时间,请使用
CONVERT_TZ()
功能:
SELECT CONVERT_TZ(created, "+0:00", @@timezone) FROM aoeui;
有关更多信息,我建议阅读/观看 Andrew Hutchings 的 正确处理时间和日期。