mko*_*ala 59 mysql timezone datetime
我有数以千计在坦桑尼亚拍摄的照片,我想在MySQL数据库中存储每张照片的日期和时间.然而,服务器位于美国,当我尝试存储坦桑尼亚日期时间时,我遇到问题,该日期时间在春季夏令时期间(在美国)处于"无效"小时内.坦桑尼亚不做DST,所以时间实际上是有效的时间.
其他复杂情况是,来自许多不同时区的合作者需要访问存储在数据库中的日期时间值.我希望他们总是作为坦桑尼亚时间出现,而不是在各个合作者所处的当地时代.
我不愿意设置会话时间因为我知道当有人忘记设置会话时间并且错过时间时会出现问题.而我无权更改服务器的任何内容.
我读过: 夏令时和时区最佳实践和 MySQL日期时间字段和夏令时 - 我如何引用"额外"时间?并 在PHP/MySQL中将日期时间存储为UTC
但它们似乎都没有解决我的特殊问题.我不是SQL专家; 有没有办法在设置DATETIME时指定时区?我还没见过一个.否则,非常感谢任何有关如何处理此问题的建议.
编辑:这是我遇到的问题的一个例子.我发送命令:
INSERT INTO Images (CaptureEvent, SequenceNum, PathFilename, TimestampJPG)
VALUES (122,1,"S2/B04/B04_R1/IMAG0148.JPG","2011-03-13 02:49:10")
Run Code Online (Sandbox Code Playgroud)
我收到错误:
Error 1292: Incorrect datetime value: '2011-03-13 02:49:10' for column 'TimestampJPG'
Run Code Online (Sandbox Code Playgroud)
这个日期和时间存在于坦桑尼亚,但不存在于数据库所在的美国.
Mat*_*int 54
你说:
我希望他们总是作为坦桑尼亚时间出现,而不是在各个合作者所处的当地时代.
如果是这种情况,那么你应该不使用UTC.您需要做的就是DATETIME在MySQL中使用类型而不是TIMESTAMP类型.
MySQL将
TIMESTAMP当前时区的值转换为UTC进行存储,然后从UTC转换回当前时区进行检索.(对于其他类型,例如,这不会发生DATETIME.)
如果您已经在使用DATETIME类型,那么您必须在当地时间之前不要设置它.您需要更少关注数据库,更多关注应用程序代码 - 您没有在此处展示.问题和解决方案将根据语言的不同而有很大差异,因此请务必使用应用程序代码的相应语言标记问题.
Mat*_* Mc 33
这里的答案都没有一针见血。
如何使用时区信息在 MySQL 中存储日期时间
使用两列:DATETIME, 和 aVARCHAR来保存时区信息,可能有几种形式:
阿时区或位置,例如America/New_York是最高的数据的保真度。
一个时区的缩写,如PST为下一个最高的保真度。
诸如此类的时间偏移-2:00是这方面的最小数据量。
一些关键点:
TIMESTAMP因为它仅限于 2038 年,并且 MySQL 将其与服务器时区相关联,这可能是不受欢迎的。INT字段中,因为存在半小时和四分之一小时的偏移。如果让 MySQL按时间顺序比较或排序这些日期对您的用例很重要,则DATETIME有一个问题:
'2009-11-10 11:00:00 -0500''2009-11-10 10:00:00 -0700'在“即时”方面是之前的,但是当插入到DATETIME.
您可以自己转换为 UTC。在上面的示例中,您将分别拥有'2009-11-10 16:00:00'和'2009-11-10 17:00:00',它们将正确排序。检索数据时,您将使用时区信息将其恢复为原始形式。
我非常喜欢的一项建议是有三列:
local_time DATETIMEutc_time DATETIME time_zone VARCHAR(X)其中 X 适合您在那里存储的数据类型。(我会为时区/位置选择 64 个字符。)3 列方法的一个优点是它是明确的:对于单个DATETIME列,您无法一眼看出它在插入之前是否已转换为 UTC。
关于通过时区/缩写/偏移量的准确性下降:
America/Juneau,您可以准确地知道他们在过去或未来的任何时间的挂钟时间(除非改变该位置处理夏令时的方式)。DST 的起点/终点,以及是否使用它,取决于位置,因此这是唯一可靠的方法。-0700,您将无法预测过去或未来的挂钟时间。例如,在美国,科罗拉多州和亚利桑那州都使用 MST,但亚利桑那州不遵守 DST。那么如果用户14:00 -0700在冬季上传他的猫照片,他是在亚利桑那州还是加利福尼亚州?如果您在该日期准确添加六个月,是为用户14:00还是13:00为用户?当您的应用程序将时间、日期或日程安排作为核心功能时,考虑这些事情很重要。
参考:
MySQL 存储没有时区信息的DATETIME 。假设您将 '2019-01-01 20:00:00' 存储到 DATETIME 字段中,当您检索该值时,您应该知道它属于哪个时区。
因此,在您的情况下,当您将值存储到 DATETIME 字段时,请确保它是坦桑尼亚时间。然后等你拿出来,就是坦桑尼亚时间了。好极了!
现在,棘手的问题是:当我执行 INSERT/UPDATE 时,如何确保该值是坦桑尼亚时间?两种情况:
你做INSERT INTO table (dateCreated) VALUES (CURRENT_TIMESTAMP or NOW())。
您这样做INSERT INTO table (dateCreated) VALUES (?),并从您的应用程序代码中指定当前时间。
情况1
MySQL 将采用当前时间,假设是 '2019-01-01 20:00:00' 坦桑尼亚时间。然后 MySQL 会将其转换为 UTC,即 '2019-01-01 17:00:00',并将该值存储到该字段中。
那么如何将坦桑尼亚时间(即“20:00:00”)存储到字段中呢?这是不可能的。从该字段读取时,您的代码需要预期 UTC 时间。
案例#2
这取决于您作为 传递的值的类型?。如果您传递字符串 '2019-01-01 20:00:00',那么对您有好处,这正是将存储到数据库的内容。如果您传递某种类型的 Date 对象,那么它将取决于数据库驱动程序如何解释该 Date 对象,以及它最终提供给 MySQL 用于存储的 'YYYY-MM-DD HH:mm:ss' 字符串。数据库驱动程序的文档应该告诉你。
TIMESTAMP时指定时区偏移量。DATETIME偏移量附加到日期时间文字的时间部分,中间没有空格,并使用与设置time_zone系统变量相同的格式,但有以下例外:
EET”和“ ”等时区名称;Asia/Shanghai' SYSTEM' 也不能在这种情况下使用。插入的值的月份部分、日期部分或两者都不能为零。从 MySQL 8.0.22 开始强制执行此操作,无论服务器 SQL 模式设置如何。
此示例说明使用不同的 time_zone 设置将带有时区偏移的日期时间值插入到TIMESTAMP和DATETIME列中,然后检索它们:
mysql> CREATE TABLE ts (
-> id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> col TIMESTAMP NOT NULL
-> ) AUTO_INCREMENT = 1;
mysql> CREATE TABLE dt (
-> id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> col DATETIME NOT NULL
-> ) AUTO_INCREMENT = 1;
mysql> SET @@time_zone = 'SYSTEM';
mysql> INSERT INTO ts (col) VALUES ('2020-01-01 10:10:10'),
-> ('2020-01-01 10:10:10+05:30'), ('2020-01-01 10:10:10-08:00');
mysql> SET @@time_zone = '+00:00';
mysql> INSERT INTO ts (col) VALUES ('2020-01-01 10:10:10'),
-> ('2020-01-01 10:10:10+05:30'), ('2020-01-01 10:10:10-08:00');
mysql> SET @@time_zone = 'SYSTEM';
mysql> INSERT INTO dt (col) VALUES ('2020-01-01 10:10:10'),
-> ('2020-01-01 10:10:10+05:30'), ('2020-01-01 10:10:10-08:00');
mysql> SET @@time_zone = '+00:00';
mysql> INSERT INTO dt (col) VALUES ('2020-01-01 10:10:10'),
-> ('2020-01-01 10:10:10+05:30'), ('2020-01-01 10:10:10-08:00');
mysql> SET @@time_zone = 'SYSTEM';
mysql> SELECT @@system_time_zone;
+--------------------+
| @@system_time_zone |
+--------------------+
| EST |
+--------------------+
mysql> SELECT col, UNIX_TIMESTAMP(col) FROM dt ORDER BY id;
+---------------------+---------------------+
| col | UNIX_TIMESTAMP(col) |
+---------------------+---------------------+
| 2020-01-01 10:10:10 | 1577891410 |
| 2019-12-31 23:40:10 | 1577853610 |
| 2020-01-01 13:10:10 | 1577902210 |
| 2020-01-01 10:10:10 | 1577891410 |
| 2020-01-01 04:40:10 | 1577871610 |
| 2020-01-01 18:10:10 | 1577920210 |
+---------------------+---------------------+
mysql> SELECT col, UNIX_TIMESTAMP(col) FROM ts ORDER BY id;
+---------------------+---------------------+
| col | UNIX_TIMESTAMP(col) |
+---------------------+---------------------+
| 2020-01-01 10:10:10 | 1577891410 |
| 2019-12-31 23:40:10 | 1577853610 |
| 2020-01-01 13:10:10 | 1577902210 |
| 2020-01-01 05:10:10 | 1577873410 |
| 2019-12-31 23:40:10 | 1577853610 |
| 2020-01-01 13:10:10 | 1577902210 |
+---------------------+---------------------+
Run Code Online (Sandbox Code Playgroud)
笔记:
TIMESTAMP值从当前时区转换为 UTC 进行存储,并从 UTC 转换回当前时区进行检索。(对于其他类型,例如 ,不会发生这种情况DATETIME。)您描述的所有症状都表明您永远不会告诉MySQL使用什么时区,因此它默认为系统区域.想一想:如果它只是'2011-03-13 02:49:10',它怎么能猜到它是坦桑尼亚当地的约会呢?
据我所知,MySQL没有提供任何语法来指定日期中的时区信息.您必须根据每个连接更改它; 就像是:
SET time_zone = 'EAT';
Run Code Online (Sandbox Code Playgroud)
如果这不起作用(要使用命名区域,您需要将服务器配置为这样做而且通常不是这种情况),您可以简单地使用UTC偏移:
SET time_zone = '+03:00';
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
108112 次 |
| 最近记录: |