我在坦桑尼亚拍摄了数千张照片,我想在MySQL数据库中存储每张照片的拍摄日期和时间。然而,服务器位于美国,当我尝试存储坦桑尼亚日期时间时,我遇到了问题,该日期时间在春季夏令时期间(在美国)处于“无效”小时内。坦桑尼亚不做DST,所以时间实际上是有效的时间。
其他复杂情况是,来自许多不同时区的协作者需要访问存储在数据库中的日期时间值。我希望他们总是作为坦桑尼亚时间出现,而不是在各个合作者所在的当地时间。
我不愿意设置会话时间,因为我知道当有人忘记设置会话时间并且错过时间时会出现问题。而我无权更改服务器的任何内容。
我读过: Daylight saving time and time zone best practices和 MySQL datetime fields and daylight savings time -- how do I reference the "extra" hour?和 Storing datetime as UTC in PHP/MySQL
但他们似乎都没有解决我的特殊问题。我不是SQL专家;有没有办法在设置DATETIME时指定时区?我还没见过一个。否则,非常感谢任何有关如何处理此问题的建议。
编辑: 这是我遇到的问题的一个例子。我发送命令:
INSERT INTO Images (CaptureEvent, SequenceNum, PathFilename, TimestampJPG)
VALUES (122,1,"S2/B04/B04_R1/IMAG0148.JPG","2011-03-13 02:49:10")
我收到错误:
Error 1292: Incorrect datetime value: '2011-03-13 02:49:10' for column 'TimestampJPG'
这个日期和时间存在于坦桑尼亚,但不存在于数据库所在的美国。
答案 0 :(得分:47)
你说:
我希望他们总是以坦桑尼亚时间出现,而不是在各个合作者所处的当地时代。
如果是这种情况,那么您应该不使用UTC。您需要做的就是在MySQL中使用DATETIME
类型而不是TIMESTAMP
类型。
MySQL将
TIMESTAMP
值从当前时区转换为UTC进行存储,然后从UTC返回到当前时区进行检索。 (对于其他类型,例如DATETIME
,不会发生这种情况。)
如果已使用DATETIME
类型,那么您必须在当地时间之前设置它。您需要更少关注数据库,更多关注应用程序代码 - 您没有在此处展示。问题和解决方案会因语言而异,因此请务必使用适当的应用程序代码语言标记问题。
答案 1 :(得分:5)
您描述的所有症状都表明您永远不会告诉MySQL使用什么时区,因此它默认为系统区域。想一想:如果它只是'2011-03-13 02:49:10'
,它怎么能猜到它是坦桑尼亚当地的日期呢?
据我所知,MySQL没有提供任何语法来指定日期中的时区信息。你必须改为per-connection basis;类似的东西:
SET time_zone = 'EAT';
如果这不起作用(要使用命名区域,您需要the server has been configured这样做而且通常不是这种情况),您可以简单地使用UTC偏移量:
SET time_zone = '+03:00';
答案 2 :(得分:3)
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对象,最终取决于它提供的'YYYY-MM-DD HH:mm:ss'字符串到MySQL进行存储。数据库驱动程序的文档应该告诉您。
答案 3 :(得分:2)
这里的答案都没有击中头部。
如何在MySQL中使用时区信息存储日期时间
使用两列:<app-content [(playlist)]="playlist"></app-content>
和@Input() playlist: any[]
来保存时区信息,该信息可以采用几种形式:
timezone或位置(例如DATETIME
)是最高的数据保真度。
次高的保真度是VARCHAR
之类的timezone abbreviation。
时间偏移量(例如America/New_York
)是最小的数据量。
一些关键点:
PST
,因为它限于2038年,而MySQL将其与服务器时区相关联,这可能是不希望的。-2:00
字段中,因为存在半小时和四分之一小时的偏移量。如果按时间顺序对这些日期进行MySQL compare 或 sort 对于您的用例来说很重要,那么TIMESTAMP
就有问题:
INT
在“即时”方面早于DATETIME
,但是当插入'2009-11-10 11:00:00 -0500'
时,它们会以其他方式排序。
您可以自己转换为UTC。在上面的示例中,您将分别具有
'2009-11-10 10:00:00 -0700'
和DATETIME
,它们将正确排序。检索数据时,您将使用时区信息将其还原为原始格式。
我很喜欢一个recommendation,其中有 3 列:
'2009-11-10 16:00:00'
'2009-11-10 17:00:00'
local_time DATETIME
,其中X适用于您在那里存储的数据类型。 (我会选择64个字符作为时区/位置。) 3列方法的一个优点是它很明确:只有一个utc_time DATETIME
列,您无法一眼就知道它在插入之前是否已转换为UTC。
关于通过时区/缩写/偏移量的准确性下降:
time_zone VARCHAR(X)
之类的用户timezone/location,则可以准确地知道他们在过去或将来的任何时间的挂钟时间(除非更改夏令时的方式,在该位置处理)。 DST的起点/终点以及是否使用,都取决于位置,因此这是唯一可靠的方法。DATETIME
),则将无法预测过去或将来的挂钟时间。例如,在美国,科罗拉多州和亚利桑那州都使用MST,但亚利桑那州未使用DST。因此,如果用户在冬季将自己的猫照片上传到America/Juneau
,那么他是在亚利桑那州还是在加利福尼亚州?如果您恰好在该日期前添加了六个月,那么用户是-0700
还是14:00 -0700
?当您的应用程序具有时间,日期或调度作为核心功能时,要考虑这些因素。
参考文献:
答案 4 :(得分:0)
我曾经也遇到过这样的问题,我需要保存供不同合作者使用的数据,最终以Unix时间戳格式存储时间,该时间表示自1970年1月以来的秒数,它是整数格式。
坦桑尼亚今天的日期和时间示例为Friday, September 13, 2019 9:44:01 PM
,当以unix时间戳存储时,该日期和时间为1568400241
现在,在读取数据时,只需使用类似php或任何其他语言的内容,然后从UNIX时间戳中提取日期。 php的示例将是
echo date('m/d/Y', 1568400241);
这甚至使与其他协作者在不同位置存储数据更加容易。他们可以使用自己的gmt偏移量将日期简单地转换为unix时间戳,并以整数格式存储,而在输出时只需使用a
进行转换即可。