我应该使用字段“date时间”还是“时间戳”?

你会推荐使用date 时间或时间戳字段,为什么(使用MySQL)?

我在服务器端使用PHP。

MySQL中的时间戳通常用于跟踪对logging的更改,并且每次logging更改时都会更新。 如果你想存储一个特定的值,你应该使用date时间字段。

如果您想要在使用UNIX时间戳或本地MySQLdate时间字段之间做出决定,请使用本机格式。 你可以用这种方式在MySQL中进行计算("SELECT DATE_ADD(my_datetime, INTERVAL 1 DAY)") ,当查询logging时,将值的格式更改为UNIX时间戳("SELECT UNIX_TIMESTAMP(my_datetime)")如果你想用PHP来操作它。

在MySQL 5及更高版本中, TIMESTAMP值从当前时区转换为UTC存储,并从UTC转换回当前时区以供检索。 (这只发生在TIMESTAMP数据types,而不是其他types如DATETIME。

默认情况下,每个连接的当前时区是服务器的时间。 时区可以在每个连接的基础上设置,如MySQL服务器时区支持中所述

除了行元数据(date创build或修改)以外,我总是使用DATETIME字段。

正如MySQL文档中提到的:

当您需要包含date和时间信息的值时,使用DATETIMEtypes。 MySQL以'YYYY-MM-DD HH:MM:SS'格式检索并显示DATETIME值。 支持的范围是“1000-01-01 00:00:00”到“9999-12-31 23:59:59”。

TIMESTAMP数据types的范围为'1970-01-01 00:00:01'UTC到'2038-01-09 03:14:07'UTC。 它具有不同的属性,具体取决于MySQL版本和服务器运行的SQL模式。

一般使用的TIMESTAMPs的下限很可能会达到 – 例如存储生日。

下面的例子显示了TIMESTAMPdatetypes在DATETIME不变time-zone to 'america/new_york'下将time-zone to 'america/new_york'更改time-zone to 'america/new_york'后如何更改值。

 mysql> show variables like '%time_zone%'; +------------------+---------------------+ | Variable_name | Value | +------------------+---------------------+ | system_time_zone | India Standard Time | | time_zone | Asia/Calcutta | +------------------+---------------------+ mysql> create table datedemo( -> mydatetime datetime, -> mytimestamp timestamp -> ); mysql> insert into datedemo values ((now()),(now())); mysql> select * from datedemo; +---------------------+---------------------+ | mydatetime | mytimestamp | +---------------------+---------------------+ | 2011-08-21 14:11:09 | 2011-08-21 14:11:09 | +---------------------+---------------------+ mysql> set time_zone="america/new_york"; mysql> select * from datedemo; +---------------------+---------------------+ | mydatetime | mytimestamp | +---------------------+---------------------+ | 2011-08-21 14:11:09 | 2011-08-21 04:41:09 | +---------------------+---------------------+ 

我已经将我的答案转换为文章,以便更多的人可以find这个有用的MySQL:Datetime和Timestamp数据types

主要区别是DATETIME是恒定的,而TIMESTAMP受time_zone设置的影响。

所以,只有当你或者将来有可能跨时区同步群集时,这一点才是重要的。

简单地说: 如果我在澳大利亚有一个数据库,并且转储该数据库以在美国同步/填充数据库,那么TIMESTAMP将更新以反映新时区中事件的实时,而DATETIME会仍然反映在au时区的事件的时间

在应用TIMESTAMP的地方使用DATETIME的一个很好的例子就是在Facebook上,他们的服务器从来不知道跨时区发生了什么事情。 一旦我开始谈话,其中有一段时间,我说在发送消息之前,我正在回复消息。 (当然,这也可能是由于消息传递软件中的时区翻译错误而造成的,如果时间被张贴而不是同步的话)。

我在一个语义基础上做出这个决定。

当我需要logging(或多或less)固定的时间点时,我使用时间戳。 例如,当logging被插入到数据库中或发生某些用户操作时。

当date/时间可以任意设置和更改时,我使用date时间字段。 例如,当用户可以保存更改后的约会。

对于DATETIME,TIMESTAMP是4个字节对8个字节。

http://dev.mysql.com/doc/refman/5.0/en/storage-requirements.html

但是就像scronide说的那样,它的确有一个1970年的下限,对于将来可能发生的任何事情来说都是很好的;)

  1. 对于DATETIME,TIMESTAMP是四个字节对八个字节。

  2. 数据库中的时间戳也更轻,索引更快。

  3. 当您需要包含date和时间信息的值时,使用DATETIMEtypes。 MySQL以'YYYY-MM-DD HH:MM:SS'格式检索并显示DATETIME值。 支持的范围是“1000-01-01 00:00:00”到“9999-12-31 23:59:59”。

TIMESTAMP数据types的范围为'1970-01-01 00:00:01'UTC到'2038-01-09 03:14:07'UTC。 它具有不同的属性,具体取决于MySQL版本和服务器运行的SQL模式。

  1. DATETIME是恒定的,而TIMESTAMP受time_zone设置的影响。

我build议不要使用DATETIME或TIMESTAMP字段。 如果你想表示一个整体的特定日子(比如生日),那么使用DATEtypes,但是如果你比这更具体,那么你可能有兴趣logging一个实际的时刻,而不是一个单位时间(日,周,月,年)。 使用BIGINT,而不是使用DATETIME或TIMESTAMP,只需存储自纪元以来的毫秒数(如果使用的是Java,则为System.currentTimeMillis())。 这有几个好处:

  1. 您避免了供应商locking。 几乎每个数据库都以相对相似的方式支持整数。 假设你想移动到另一个数据库。 您是否想担心MySQL的DATETIME值与Oracle如何定义它们之间的差异? 即使在不同版本的MySQL中,TIMESTAMPS也具有不同的精确度。 直到最近,MySQL才在时间戳中支持毫秒。
  2. 没有时区问题。 关于不同数据types的时区会发生什么,这里有一些有见地的评论。 但是,这是常识,你的同事们会花时间去学习吗? 另一方面,把BigINT改成java.util.Date是相当困难的。 使用BIGINT会导致时区的许多问题被解决。
  3. 不用担心范围或精度。 您不必担心未来的date范围会缩短什么(TIMEZONE只能到2038年)。
  4. 第三方工具集成。 通过使用一个整数,第三方工具(例如EclipseLink)与数据库接口是微不足道的。 并不是每个第三方工具都会像MySQL那样对“date时间”有相同的理解。 想尝试在Hibernate中弄清楚,如果你使用这些自定义数据types,是否应该使用java.sql.TimeStamp或java.util.Date对象? 使用您的基本数据types使用第三方工具琐碎。

这个问题是密切相关的,你应该如何在数据库中存储货币价值(即1.99美元)。 你应该使用十进制还是数据库的Moneytypes,或者最糟糕的是Double? 所有这些选项都是可怕的,因为上面列出的许多相同的原因。 解决scheme是使用BIGINT存储货币价值,然后在将价值显示给用户时将美分转换为美元。 数据库的工作是存储数据,而不是解释这些数据。 在数据库(尤其是Oracle)中看到的所有这些奇特的数据types几乎不会增加,并且可以让您走上供应商locking的道路。

取决于应用,真的。

考虑设置一个用户在纽约的服务器的时间戳,在桑海预约。 现在,当用户连接到桑海时,他从东京的镜像服务器访问相同的预约时间戳。 他将在东京时间看到这个任命,从原来的纽约时代抵消。

所以对于像约会或时间表那样代表用户时间的值,date时间更好。 它允许用户控制所需的确切date和时间,而不pipe服务器设置如何。 设置的时间是设置的时间,不受服务器的时区,用户的时区,或夏时制的计算方式的变化(是的,它会改变)的影响。

另一方面,对于代表系统时间的值,如支付交易,表格修改或logging,始终使用时间戳。 将服务器移至其他时区或在不同时区的服务器之间进行比较时,系统不会受到影响。

数据库中的时间戳也更轻,索引更快。

timestamp字段是datetime timestamp字段的特例。 您可以创buildtimestamp列以具有特殊属性; 可以将其设置为在创build和/或更新时自行更新。

在“更大”的数据库术语中, timestamp有几个特殊的触发器。

什么是正确的完全取决于你想要做什么。

TIMESTAMP始终使用UTC(即自1970-01-01以来以秒计算),并且MySQL服务器会自动将其转换为服务器时区的date/时间。 从长远来看,TIMESTAMP是要走的路,因为你知道你的时态数据总是用UTC。 例如,如果您迁移到其他服务器或者更改了服务器上的时区设置,则不会影响date。

在MySQL中值得注意的是,在创build表列时,您可以使用下面的代码:

 on update CURRENT_TIMESTAMP 

这将更新每个修改行的实例的时间,有时对于存储的最后编辑信息非常有帮助。 这只适用于时间戳,但不是date时间。

2016 + :我build议将您的Mysql时区设置为UTC并使用DATETIME:

任何最近的前端框架(Angular 1/2,react,Vue,…)都可以轻松自动地将UTCdate时间转换为当地时间。

另外:

  • DATETIME现在可以自动设置为当前时间值如何为MySQL Datetime列设置默认值?
  • 相反,人们可能会认为,DATETIME是更快的时间戳, http : //gpshumano.blogs.dri.pt/2009/07/06/mysql-datetime-vs-timestamp-vs-int-performance-and-benchmarkingwithwith -myisam /
  • 时间戳仍然限于1970 – 2038年

(除非你可能会改变你的服务器的时区)


以AngularJs为例

 // back-end: format for angular within the sql query SELECT DATE_FORMAT(my_datetime, "%Y-%m-%dT%TZ")... // font-end Output the localised time {{item.my_datetime | date :'medium' }} 

所有本地化的时间格式在这里可用: https : //docs.angularjs.org/api/ng/filter/date

在使用MySQL和PHP时,我总是使用Unix时间戳。 这是PHP的默认date方法的主要原因是使用时间戳作为参数,所以不需要parsing。

为了在PHP中获得当前的Unix时间戳,只需要time();
并在MySQL中做SELECT UNIX_TIMESTAMP();

我总是使用Unix时间戳,只是为了在处理大量date时间信息时保持清醒,特别是在执行时区调整,加/减date等时。 比较时间戳时,这排除了时区的复杂因素,并允许您在服务器端处理(无论是应用程序代码还是数据库查询)中占用资源,因为您使用轻量级算术而不是较重的date – 时间加/减function。

另一件值得考虑的事情

如果你正在构build一个应用程序,你永远不知道你的数据可能不得不被使用。 如果你不得不说比较数据集中的一堆logging,比如来自第三方API的一些logging,并且按时间顺序排列,那么你会很高兴你的行的Unix时间戳。 即使您决定使用MySQL时间戳,也会将Unix时间戳存储为保险。

Timestamp和Datetime之间的另一个区别是在Timestamp中,您不能将默认值设置为NULL。

根据我的经验,如果你想要一个插入只发生一次的date字段,你不希望有任何更新或任何其他行动在该特定领域,与date时间

例如,考虑具有REGISTRATION DATE字段的user表。 在该user表中,如果您想知道特定用户的上次login时间,请使用时间戳记types字段,以便更新该字段。

如果从phpMyAdmin创build表,默认设置将更新行更新时更新时间戳字段。 如果您的时间戳记字段没有使用行更新进行更新,则可以使用以下查询使时间戳字段得到自动更新。

 ALTER TABLE your_table MODIFY COLUMN ts_activity TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP; 

时间戳记数据types存储date和时间,但以UTC格式存储,不像date时间那样处于当前时区格式。 当你获取数据,时间戳再次转换成当前的时区时间。

所以假设你在美国,并从美国有一个时区的服务器获取数据。 然后根据美国时区获取date和时间。 时间戳记数据types列在更新行时总是自动更新。 因此,追踪上一次更新特定行的时间会很有用。

有关更多详细信息,您可以阅读博客文章Timestamp Vs Datetime

当您在表上执行UPDATE语句时,请注意更改时间戳。 如果您有一个包含“名称”(varchar),“年龄”(int)和“Date_Added”(时间戳)列的表,并且运行以下DML语句

 UPDATE table SET age = 30 

那么'Date_Added'列中的每个值都会被更改为当前的时间戳。

主要区别在于

  • 时间戳上的索引 – 作品
  • date时间上的INDEX – 不起作用

看看这篇文章,看看date时间索引的问题

我发现TIMESTAMP能够在不使用不必要的触发器的情况下根据当前时间自动更新自身,这是非常有用的。 虽然这只是我,虽然TIMESTAMP是UTC就像它说的。

它可以跟踪不同的时区,所以如果你需要显示相对时间,UTC时间是你想要的。

我更喜欢使用时间戳,以便将所有内容保存在一个通用的原始格式中,并将数据格式化为PHP代码或SQL查询。 在你的代码中有一些方便的地方可以让所有的东西在一秒钟之内完成。

从这篇文章中引用:

主要区别:

TIMESTAMP用于跟踪对logging的更改,并在每次更改logging时进行更新。 DATETIME用于存储不受logging中任何更改影响的特定值和静态值。

TIMESTAMP也受到不同时区相关设置的影响。 DATETIME是不变的。

TIMESTAMP内部将当前时区转换为UTC存储,并在检索期间转换回当前时区。 DATETIME不能这样做。

TIMESTAMP支持的范围:'1970-01-01 00:00:01'UTC到'2038-01-19 03:14:07'UTC DATETIME支持的范围:'1000-01-01 00:00:00'到'9999 -12-31 23:59:59'

DATETIME,TIMESTAMP和DATE之间的比较

在这里输入图像描述

那是什么[.fraction]?

  • DATETIME或TIMESTAMP值可以包含以微秒(6位)为精度的尾随小数秒部分。 特别是插入DATETIME或TIMESTAMP列的值中的小数部分被存储而不是丢弃。 这当然是可选的。

资料来源:

  • MySQLdate/时间数据types参考
  • MySQL存储需求参考

我喜欢Unix的时间戳,因为你可以转换为数字,只是担心数字。 加上你加/减,得到持续时间等,然后将结果转换为任何格式的date。 此代码可以查找从文档的时间戳到当前时间之间以分钟为单位的时间。

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

一个TIMESTAMP需要4个字节,而一个DATETIME需要8个字节。

就我而言,我将UTC设置为所有事物的时区:系统,数据库服务器等,每次我都可以。 如果我的客户需要另一个时区,那么我在应用程序上configuration它。

我几乎总是更喜欢时间戳,而不是date时间字段,因为时间戳隐式地包含时区。 因此,由于应用程序将从不同时区的用户访问,并且希望他们在本地时区中查看date和时间,因此与数据保存在date时间字段中相比,此字段types使其非常容易。

另外,如果将数据库迁移到另一个时区的系统,我会更加自信地使用时间戳。 在计算两个时刻之间的差异时,不要说可能出现的问题,其中苏美时间之间的差异需要1小时或更less的精度。

所以,总结一下,我重视这个时间戳的优点:

  • 准备在国际(多时区)应用程序上使用
  • 在时区之间轻松迁移
  • 很容易计算差异(只是减去两个时间戳)
  • 无需担心date在夏季的时间

For all this reasons, I choose UTC & timestamp fields where posible. And I avoid headaches 😉

Not mentioned so far, is that DEFAULT CURRENT_TIMESTAMP only works with Timestamp, but not DateTime type fields.

This becomes relevant for MS Access tables which can only use DateTime but not Timestamp.

A lot of answers here suggest to store as timestamp in the case you have to represent well defined points in time. But you can also have points in time with datetime if you store them all in UTC by convention.