如何使用时区信息在MySQL中存储日期时间

时间:2013-11-07 17:56:33

标签: mysql datetime timezone

我在坦桑尼亚拍摄了数千张照片,我想在MySQL数据库中存储每张照片的拍摄日期和时间。然而,服务器位于美国,当我尝试存储坦桑尼亚日期时间时,我遇到了问题,该日期时间在春季夏令时期间(在美国)处于“无效”小时内。坦桑尼亚不做DST,所以时间实际上是有效的时间。

其他复杂情况是,来自许多不同时区的协作者需要访问存储在数据库中的日期时间值。我希望他们总是作为坦桑尼亚时间出现,而不是在各个合作者所在的当地时间。

我不愿意设置会话时间,因为我知道当有人忘记设置会话时间并且错过时间时会出现问题。而我无权更改服务器的任何内容。

我读过: Daylight saving time and time zone best practicesMySQL 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'

这个日期和时间存在于坦桑尼亚,但不存在于数据库所在的美国。

5 个答案:

答案 0 :(得分:47)

你说:

  

我希望他们总是以坦桑尼亚时间出现,而不是在各个合作者所处的当地时代。

如果是这种情况,那么您应该使用UTC。您需要做的就是在MySQL中使用DATETIME类型而不是TIMESTAMP类型。

From the MySQL documentation

  

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时,如何确定值是坦桑尼亚时间?两种情况:

  1. 您做INSERT INTO table (dateCreated) VALUES (CURRENT_TIMESTAMP or NOW())

  2. 您执行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的起点/终点以及是否使用,都取决于位置,因此这是唯一可靠的方法。
  • 如果您有timezone abbreviation(例如MST)(山标准时间)或普通偏移量(例如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

进行转换即可。