您建议使用datetime或timestamp字段吗?为什么(使用MySQL)?

我在服务器端使用PHP。


当前回答

DATETIME不携带时区信息,并且将始终显示与会话有效的时区无关的时区,除非您明确更改它,否则默认为服务器的时区。但是,如果我使用NOW()之类的函数而不是“2020-01-16 12:15:00”之类的文字来初始化DATETIME列,是本地化到会话时区的当前日期和时间。

相比之下,TIMESTAMP确实隐式地携带时区信息:当您使用值初始化TIMESTAMP列时,该值在存储之前会转换为UTC。如果存储的值是文本,例如“2020-01-16 12:15:00”,则出于转换目的,它被解释为在会话的当前时区中。相反,当显示TIMESTAMP列时,它将首先从UTC转换为会话的当前时区。

什么时候使用一个或另一个?案例研究

一个社区剧团的网站正在播放几场正在售票的戏剧演出。这些演出的日期和时间将显示在下拉列表中,希望购买演出门票的客户将从中选择一个。数据库列performance_date_and_time为DATETIME类型是有意义的。如果演出地点在纽约,则有一种理解,即有一个隐含的时区(“纽约当地时间”),理想情况下,我们希望日期和时间显示为“2019年12月12日晚上8点”,而不考虑会议的时区,也不必麻烦进行任何时区转换。

另一方面,一旦2019年12月12日晚上8点的演出开始,我们可能不再想出售门票,因此不再在下拉列表中显示该演出。因此,我们想知道“2019-12-12 20:00:00”是否已发生。这将证明有一个TIMESTAMP列,将会话的时区设置为“America/New_York”,并将会话time_zone设置为“American/New_约克”,然后将“2019-12-12 20:00:00”存储到TIMESTAMP栏中。从此,我们可以通过独立于当前会话时区将此列与NOW()进行比较来测试性能是否已开始。

或者,为这两个单独的目的设置DATETIME和TIMESTAMP列可能是有意义的。或者不是。显然,任何一个都可以达到这两个目的。如果只使用DATETIME列,则在与NOW()进行比较之前,必须将当前时区设置为本地时区。如果只使用TIMESTAMP列,则必须在显示该列之前将会话时区设置为本地时区。

其他回答

MySQL中的时间戳通常用于跟踪记录的更改,并且经常在每次更改记录时更新。如果要存储特定值,应使用datetime字段。

如果您希望在使用UNIX时间戳或本机MySQL日期时间字段之间做出选择,请使用本机datetime格式。您可以通过这种方式在MySQL中进行计算(“SELECT DATE_ADD(my_datetime,INTERVAL 1 DAY)”),如果您想用PHP对记录进行操作,那么在查询记录时,很容易将值的格式更改为UNIX时间戳(“SELECT UNIX_timestamp(my_datatime)”)。

我喜欢Unix时间戳,因为你可以转换成数字,只需担心数字。此外,您还可以添加/减去和获取持续时间等。然后将结果转换为任何格式的日期。这段代码找出文档的时间戳和当前时间之间经过了多少时间(以分钟为单位)。

$date  = $item['pubdate']; (etc ...)
$unix_now = time();
$result = strtotime($date, $unix_now);
$unix_diff_min = (($unix_now  - $result) / 60);
$min = round($unix_diff_min);

在遇到许多与时区相关的问题和错误后,我停止在应用程序中使用datetime。在大多数情况下,IMHO使用时间戳优于datetime。

当你问什么时候?答案类似于“2019-02-05 21:18:30”,这不是完整的,也不是定义的答案,因为它缺少另一部分,在哪个时区?华盛顿?莫斯科北京?

使用不带时区的日期时间意味着您的应用程序只处理一个时区,但时间戳为您提供了日期时间的好处,以及在不同时区显示相同精确时间点的灵活性。

以下是一些会让您后悔使用datetime并希望将数据存储在时间戳中的情况。

为了客户的舒适,您希望根据他们首选的时区向他们显示时间,而不让他们做数学运算,并将时间转换为有意义的时区。您只需更改时区,所有应用程序代码都将相同。(实际上,您应该始终在应用程序开始时定义时区,或者在PHP应用程序中定义请求处理)SET time_zone=“+2:00”;您改变了所居住的国家,并继续维护数据,同时在不同的时区查看数据(而不更改实际数据)。您接受来自世界各地不同客户的数据,每个客户都会在自己的时区中插入时间。

简言之

datetime=应用程序支持1个时区(用于插入和选择)

timestamp=应用程序支持任何时区(用于插入和选择)


这个答案只是为了强调时区的灵活性和易用性,它没有涵盖任何其他差异,如列大小、范围或分数。

主要区别在于

时间戳上的索引-有效日期时间上的索引-不起作用

看看这篇文章,看看Datetime索引的问题

DATETIME类型用于包含日期和时间部分的值。MySQL以格式检索并显示DATETIME值。支持的范围为。'YYYY-MM-DD hh:MM:ss''1000-01-01 00:00:00''9999-12-31 23:59:59'

TIMESTAMP数据类型用于包含日期和时间部分的值。TIMESTAMP的范围从“1970-01-01 00:00:01”UTC到“2038-01-19 03:14:07”UTC。

mysql> SELECT col,
     >     CAST(col AT TIME ZONE INTERVAL '+00:00' AS DATETIME) AS ut
     >     FROM ts ORDER BY id;
+---------------------+---------------------+
| col                 | ut                  |
+---------------------+---------------------+
| 2020-01-01 10:10:10 | 2020-01-01 15:10:10 |
| 2019-12-31 23:40:10 | 2020-01-01 04:40:10 |
| 2020-01-01 13:10:10 | 2020-01-01 18:10:10 |
| 2020-01-01 10:10:10 | 2020-01-01 15:10:10 |
| 2020-01-01 04:40:10 | 2020-01-01 09:40:10 |
| 2020-01-01 18:10:10 | 2020-01-01 23:10:10 |
+---------------------+---------------------+

URL MySQL 8.0:https://dev.mysql.com/doc/refman/8.0/en/datetime.html