答案 0 :(得分:1697)
MySQL中的时间戳通常用于跟踪记录的更改,并且通常在每次更改记录时更新。如果要存储特定值,则应使用日期时间字段。
如果您想要在使用UNIX时间戳或本机MySQL日期时间字段之间做出决定,请使用本机格式。您可以通过这种方式在MySQL中进行计算
("SELECT DATE_ADD(my_datetime, INTERVAL 1 DAY)")
如果要使用PHP对其进行操作,则在查询记录时将值的格式更改为UNIX时间戳("SELECT UNIX_TIMESTAMP(my_datetime)")
很简单。
答案 1 :(得分:869)
在MySQL 5及更高版本中, TIMESTAMP 值从当前时区转换为UTC进行存储,并从UTC转换回当前时区以进行检索。 (这仅适用于TIMESTAMP数据类型,不适用于等其他类型,例如DATETIME。)
默认情况下,每个连接的当前时区是服务器的时间。时区可以基于每个连接进行设置,如 MySQL Server Time Zone Support 中所述。
答案 2 :(得分:477)
我总是将DATETIME字段用于行元数据以外的任何内容(创建或修改日期)。
MySQL文档中的mentioned:
当您需要包含日期和时间信息的值时,将使用DATETIME类型。 MySQL以'YYYY-MM-DD HH:MM:SS'格式检索并显示DATETIME值。支持的范围是'1000-01-01 00:00:00'到'9999-12-31 23:59:59'。
...
TIMESTAMP数据类型的范围为'1970-01-01 00:00:01'UTC到'2038-01-09 03:14:07'UTC。它具有不同的属性,具体取决于MySQL版本和运行服务器的SQL模式。
您很可能在一般使用中达到TIMESTAMP的下限 - 例如存储生日。
答案 3 :(得分:304)
以下示例显示TIMESTAMP
日期类型在更改time-zone to 'america/new_york'
后DATETIME
未更改的位置时如何更改值。
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 |
+---------------------+---------------------+
我已将我的答案转换为文章,以便更多人发现这有用, MySQL: Datetime Versus Timestamp Data Types 。
答案 4 :(得分:186)
主要区别在于DATETIME是常数,而TIMESTAMP受time_zone
设置的影响。
因此,只有当您拥有 - 或者将来可能 - 跨时区同步群集时才会这么做。
简单来说:如果我在澳大利亚有一个数据库,并且转储该数据库以同步/填充美国的数据库,那么TIMESTAMP将更新以反映新事件的实际时间时区,而DATETIME仍会反映该时区的事件时间。
在应用TIMESTAMP的情况下使用DATETIME的一个很好的例子是在Facebook,他们的服务器永远不能确定跨时区发生的时间。一旦我进行了一次对话,其中的时间表示我在实际发送消息之前回复了消息。 (当然,如果发布时间而不是同步时间,也可能是由于消息传递软件中的时区转换不良造成的。)
答案 5 :(得分:118)
我在语义基础上做出这个决定。
当我需要记录(或多或少)固定时间点时,我使用时间戳。例如,当记录插入数据库或发生某些用户操作时。
当日期/时间可以任意设置和更改时,我使用日期时间字段。例如,当用户可以保存以后更改约会时。
答案 6 :(得分:94)
对于DATETIME,TIMESTAMP是4字节Vs 8字节。
http://dev.mysql.com/doc/refman/5.0/en/storage-requirements.html
但是像scronide说它确实有一个1970年的下限。虽然对未来可能会发生的任何事情都很好;)
答案 7 :(得分:93)
我建议使用 DATETIME或TIMESTAMP字段。如果你想要表示一个特定的日子(如生日),那么使用DATE类型,但如果你比那更具体,你可能有兴趣记录一个实际的时刻,而不是一个单位的时间(日,周,月,年)。使用BIGINT而不是使用DATETIME或TIMESTAMP,只需存储自纪元以来的毫秒数(如果您使用的是Java,则为System.currentTimeMillis())。这有几个好处:
此问题与您应如何在数据库中存储货币价值(即1.99美元)密切相关。你应该使用Decimal,还是数据库的Money类型,或者最糟糕的Double?由于上面列出的许多相同原因,所有这三个选项都很糟糕。解决方案是使用BIGINT将货币价值存储在美分中,然后在向用户显示价值时将美分转换为美元。数据库的工作是存储数据,而不是用于表示数据。您在数据库(尤其是Oracle)中看到的所有这些奇特的数据类型几乎没有增加,并且开始向供应商锁定。
答案 8 :(得分:92)
对于DATETIME,TIMESTAMP是4个字节对8个字节。
数据库上的时间戳也较轻,索引速度更快。
当您需要包含日期和时间信息的值时,将使用DATETIME类型。 MySQL以'YYYY-MM-DD HH:MM:SS'格式检索并显示DATETIME值。支持的范围是'1000-01-01 00:00:00'到'9999-12-31 23:59:59'。
TIMESTAMP数据类型的范围为'1970-01-01 00:00:01'UTC到'2038-01-09 03:14:07'UTC。它具有不同的属性,具体取决于MySQL版本和运行服务器的SQL模式。
答案 9 :(得分:44)
真的取决于申请。
考虑将用户的时间戳设置为纽约的服务器,以便在Sanghai进行预约。现在,当用户在Sanghai连接时,他从东京的镜像服务器访问相同的约会时间戳。他将在东京时间看到这个任命,与原来的纽约时间相抵消。
因此,对于表示用户时间(如约会或计划)的值,日期时间更好。无论服务器设置如何,它都允许用户控制所需的确切日期和时间。设定时间是设定时间,不受服务器时区,用户时区的影响,也不受夏令时计算方式的影响(是的,确实会改变)。
另一方面,对于表示系统时间的值,如支付交易,表修改或记录,请始终使用时间戳。将服务器移动到另一个时区,或者在不同时区的服务器之间进行比较时,系统不会受到影响。
时间戳在数据库上也更轻,索引速度更快。
答案 10 :(得分:38)
任何最新的前端框架(Angular 1/2,react,Vue,...)都可以轻松自动地将您的UTC日期时间转换为当地时间。
此外:
(除非您可能更改服务器的时区)
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
答案 11 :(得分:34)
timestamp
字段是datetime
字段的特例。您可以创建timestamp
列以具有特殊属性;它可以设置为在创建和/或更新时更新自己。
在“更大”的数据库术语中,timestamp
上有几个特殊情况触发器。
正确的取决于你想做什么。
答案 12 :(得分:30)
TIMESTAMP始终为UTC(即1970-01-01以来经过的秒数,以UTC为单位),您的MySQL服务器会自动将其转换为连接时区的日期/时间。从长远来看,TIMESTAMP是最佳选择,因为您知道您的时态数据将始终为UTC。例如,如果您迁移到其他服务器或更改服务器上的时区设置,则不会搞砸日期。
注意:默认连接时区是服务器时区,但每个会话都可以(应该)更改(参见SET time_zone = ...
)。
答案 13 :(得分:26)
DATETIME,TIMESTAMP和DATE之间的比较
那是什么[.fraction]?
来源:
答案 14 :(得分:24)
值得注意的是,在MySQL中,您可以在创建表格列时使用下面的内容:
on update CURRENT_TIMESTAMP
这将更新您修改行的每个实例的时间,有时对存储的最后编辑信息非常有帮助。这仅适用于时间戳,而不适用于日期时间。
答案 15 :(得分:21)
在使用MySQL和PHP时,我总是会使用Unix时间戳。这是PHP中默认的date方法的主要原因是使用时间戳作为参数,因此不需要解析。
要获取PHP中的当前Unix时间戳,只需执行time();
在MySQL中SELECT UNIX_TIMESTAMP();
。
答案 16 :(得分:16)
根据我的经验,如果您想要一个只插入一次的日期字段,并且您不希望对该特定字段进行任何更新或任何其他操作,请使用日期时间。
例如,考虑一个带有 REGISTRATION DATE 字段的user
表。在user
表中,如果您想知道特定用户的上次登录时间,请使用时间戳字段,以便更新字段。
如果您要从phpMyAdmin创建表格,则默认设置会在发生行更新时更新时间戳字段。如果您的时间戳记未通过行更新进行更新,则可以使用以下查询使时间戳字段自动更新。
ALTER TABLE your_table
MODIFY COLUMN ts_activity TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
答案 17 :(得分:15)
时间戳数据类型存储日期和时间,但是以UTC格式存储,而不是像datetime那样以当前时区格式存储。当您获取数据时,时间戳再次将其转换为当前时区时间。
假设您在美国并从具有美国时区的服务器获取数据。然后,您将根据美国时区获取日期和时间。时间戳数据类型列在其行更新时始终自动更新。因此,跟踪上次更新特定行的时间非常有用。
有关详情,请参阅博客文章 Timestamp Vs Datetime 。
答案 18 :(得分:14)
我总是使用Unix时间戳,只是为了在处理大量日期时间信息时保持理智,特别是在执行时区调整,添加/减去日期等时。在比较时间戳时,这排除了时区的复杂因素,并允许您在服务器端处理(无论是应用程序代码还是数据库查询)中节省资源,因为您使用轻量级算术而不是更重的日期时间加/减功能。
另一件值得考虑的事情是:
如果您正在构建应用程序,那么您永远不会知道如何在线下使用您的数据。如果你不得不比较你的数据集中的一堆记录,比如来自第三方API的一堆项目,并说,按照时间顺序排列它们,你会很高兴有您的行的Unix时间戳。即使您决定使用MySQL时间戳,也要将Unix时间戳存储为保险。
答案 19 :(得分:14)
当您对表执行UPDATE语句时,请注意时间戳更改。如果您有一个包含列'Name'(varchar),'Age'(int)和'Date_Added'(timestamp)的表,并运行以下DML语句
UPDATE table
SET age = 30
然后'Date_Added'列中的每个值都将更改为当前时间戳。
答案 20 :(得分:13)
Reference taken from this Article:
主要区别:
TIMESTAMP用于跟踪记录的更改,并在每次更改记录时更新。 DATETIME用于存储特定值和静态值,不受记录中任何更改的影响。
TIMESTAMP也受到与TIME ZONE相关的不同设置的影响。 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'
答案 21 :(得分:12)
就我而言,我每次都将UTC设置为所有内容的时区:系统,数据库服务器等。如果我的客户需要另一个时区,那么我在应用程序上配置它。
我几乎总是喜欢时间戳而不是日期时间字段,因为时间戳隐式包含时区。因此,既然应用程序将从不同时区的用户访问,并且您希望他们在本地时区中查看日期和时间,那么此字段类型使得执行此操作非常容易,而不是将数据保存在日期时间字段中
另外,在将数据库迁移到具有其他时区的系统的情况下,我会更自信地使用时间戳。不是说在计算两个时刻之间的差异时可能出现的问题,其中时间间隔发生变化,需要1小时或更短的精度。
总而言之,我重视时间戳的这一优势:
出于所有这些原因,我选择UTC&有效的时间戳字段。我避免头痛;)
答案 22 :(得分:10)
答案 23 :(得分:10)
Timestamp和Datetime之间的另一个区别是在Timestamp中,您不能将默认值设置为NULL。
答案 24 :(得分:10)
我发现TIMESTAMP能够在不使用不必要的触发器的情况下根据当前时间自动更新自身的能力无与伦比。这只是我,虽然TIMESTAMP是UTC,就像它说的那样。
它可以跟踪不同的时区,因此如果您需要显示相对时间,则UTC时间就是您想要的。
答案 25 :(得分:8)
我更喜欢使用时间戳,以便将所有内容保存为一种通用的原始格式,并在PHP代码或SQL查询中格式化数据。在某些情况下,它会在您的代码中派上用场,以便在几秒钟内保留所有内容。
答案 26 :(得分:8)
+---------------------------------------------------------------------------------------+--------------------------------------------------------------------------+
| TIMESTAMP | DATETIME |
+---------------------------------------------------------------------------------------+--------------------------------------------------------------------------+
| TIMESTAMP requires 4 bytes. | DATETIME requires 8 bytes. |
| Timestamp is the number of seconds that have elapsed since January 1, 1970 00:00 UTC. | DATETIME is a text displays 'YYYY-MM-DD HH:MM:SS' format. |
| TIMESTAMP supported range: ‘1970-01-01 00:00:01′ UTC to ‘2038-01-19 03:14:07′ UTC. | DATETIME supported range: ‘1000-01-01 00:00:00′ to ‘9999-12-31 23:59:59′ |
| TIMESTAMP during retrieval converted back to the current time zone. | DATETIME can not do this. |
| TIMESTAMP is used mostly for metadata i.e. row created/modified and audit purpose. | DATETIME is used mostly for user-data. |
+---------------------------------------------------------------------------------------+--------------------------------------------------------------------------+
答案 27 :(得分:7)
我喜欢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);
答案 28 :(得分:6)
TIMESTAMP
需要4个字节,而DATETIME
需要8个字节。
答案 29 :(得分:4)
我只是在存储UTC时使用无符号BIGINT
...
然后仍可以在PHP中调整到当地时间。
DATETIME
选择FROM_UNIXTIME( integer_timestamp_column )
。
显然应该在该列上设置索引,否则就没有进展。
答案 30 :(得分:4)
目前尚未提及,DEFAULT CURRENT_TIMESTAMP仅适用于Timestamp,但不适用于DateTime类型字段。
这与只能使用DateTime而不使用Timestamp的MS Access表相关。
答案 31 :(得分:4)
如果来自不同国家/地区的访问者拥有不同的时区,则TIMESTAMP非常有用。您可以轻松地将TIMESTAMP转换为任何国家/地区时区
答案 32 :(得分:3)
这里有很多答案建议在时间戳中存储,你必须代表明确定义的时间点。但是,如果按惯例将它们全部存储在UTC中,您还可以获得日期时间点。
答案 33 :(得分:3)
在遇到许多与时区有关的问题和错误后,我停止在应用程序中使用datetime
。 在大多数情况下,使用timestamp
的IMHO优于datetime
。
当您问几点了?答案来了像'2019-02-05 21:18:30'之类的东西,它没有完成,没有定义答案,因为它缺少另一个部分,在哪个时区?华盛顿?莫斯科?北京?
使用不带时区的日期时间意味着您的应用程序仅处理1个时区,但是时间戳为您提供了datetime
的优势以及在不同时区中显示相同精确时间点的灵活性。
在某些情况下,会让您后悔使用datetime
并希望您将数据存储在时间戳中。
为了给客户带来安慰,您想根据他们的首选时区向他们显示时间,而无需让他们进行数学运算并将时间转换为有意义的时区。您所需要做的就是更改时区,并且所有应用程序代码都将相同。(实际上,您应始终在应用程序开始时定义时区,如果是PHP应用程序,则应请求处理) < / p>
SET time_zone = '+2:00';
您更改了所居住的国家,并继续维护数据,同时在其他时区查看数据(不更改实际数据)。
datetime
=应用程序支持1个时区(用于插入和选择)
timestamp
=应用程序支持任何时区(用于插入和选择)
此答案仅用于强调时区的灵活性和时间戳的易用性,并未涵盖column size or range or fraction之类的任何其他差异。
答案 34 :(得分:2)
DATETIME
不含任何时区信息,并且始终显示与会话有效的时区无关的信息,除非您已明确更改,否则默认为服务器时区。但是,如果我使用诸如DATETIME
之类的函数而不是像诸如NOW()
之类的文字来初始化'2020-01-16 12:15:00'
列,那么存储的值当然将是当前的本地日期和时间会话的时区。
相反,TIMESTAMP
确实隐含了时区信息:当您使用值初始化TIMESTAMP
列时,该值将在存储之前转换为UTC。如果要存储的值是诸如'2020-01-16 12:15:00'
之类的文字,则出于转换目的,它将被解释为位于会话的当前时区中。相反,显示TIMESTAMP
列时,它将首先从UTC转换为会话的当前时区。
何时使用一个或另一个?案例研究
一个社区剧院团体的网站正在展示其正在出售门票的戏剧的几场表演。这些表演的日期和时间将显示在一个下拉列表中,希望购买表演门票的客户将从中选择一个。数据库列performance_date_and_time
是DATETIME
类型是有意义的。如果演出是在纽约进行的,则应了解会涉及一个隐式时区(“纽约当地时间”),并且理想情况下,我们希望日期和时间显示为“ 2019年12月12日,8:00 PM”。不论会话的时区如何,而且都不必进行任何时区转换。
另一方面,一旦2019年12月12日晚上8点开始演出,我们可能不再想要出售门票并因此不再在下拉列表中显示该演出。因此,我们希望能够知道是否已发生'2019-12-12 20:00:00'。那会争辩说有一个TIMESTAMP
列,使用set session time_zone='America/New_York'
将会话的时区设置为'America / New_York',然后将'2019-12-12 20:00:00'
存储到TIMESTAMP
列中。此后,我们可以通过与当前会话时区无关的将此列与NOW()
进行比较来测试性能是否已经开始。
或者出于这两个单独的目的而拥有DATETIME
和TIMESTAMP
列可能很有意义。或不。显然,任何一个都可以达到两个目的。如果仅使用DATETIME
列,则必须在与NOW()
比较之前将当前时区设置为本地时区。如果仅使用TIMESTAMP
列,则必须在显示该列之前将会话时区设置为本地时区。
答案 35 :(得分:1)
如果要保证您的应用程序在2038年2月不起作用,请使用TIMESTAMP。有关支持的日期范围,请参考您的REFMAN。
答案 36 :(得分:1)
都不是。对于通用用例,DATETIME
和TIMESTAMP
类型从根本上被破坏了。 MySQL将来会更改它们。除非有特殊原因,否则应使用BIGINT
和UNIX时间戳。
在某些特定情况下,您的选择更加容易,并且在此答案中不需要分析和一般建议。
仅日期-如果您只关心日期(例如下一个农历新年的日期2020-02-25),并且对以下时区有清楚的了解日期适用(或无关紧要,如农历新年),则使用DATE
列类型。
记录插入时间-如果您正在记录数据库中行的插入日期/时间,而不必关心应用程序will break in the next 19 years,则继续使用TIMESTAMP
,默认值为CURRENT_TIMESTAMP()
。
TIMESTAMP
坏了? TIMESTAMP
类型以UTC时区存储在磁盘上。这意味着,如果您物理移动服务器,它不会损坏。很好✅。但是目前定义的时间戳记将在2038年❌完全停止工作。
每次INSERT INTO
或SELECT FROM
的{{1}}列时,都会考虑客户端/应用程序服务器的物理位置(即时区配置)。如果您移动应用程序服务器,则日期会中断❌。
TIMESTAMP
坏了? DATETIME
在同一列中存储DATETIME
和DATE
。除非了解了时区,并且时区未存储在任何地方,否则这些东西都没有任何意义。您应该在列中输入预期的时区作为注释,因为时区与数据有着千丝万缕的联系。很少有人使用列注释,因此这是等待发生的错误。我从亚利桑那州继承了一个服务器,因此我总是需要将所有时间戳从亚利桑那时间转换为另一个时间。
TIME
唯一正确的情况是完成这句话:
您的2020年太阳新年恰好是
DATETIME
。
DATETIME("2020-01-01 00:00:00")
没有其他好处。也许您会想象特拉华州的一个市政府使用Web服务器。当然,可以暗示此服务器的时区和所有访问此服务器的人都在特拉华州,并且是东部时区,对吗?错误!在这个千年中,我们都认为服务器存在于“云”中。因此,在任何特定时区都想不到您的服务器总是错误的,因为您的服务器将在某天移动。
DATETIME
?定义:
BIGINT
插入特定值:
CREATE TEMPORARY TABLE good_times (
a_time BIGINT
)
当然,这比您的应用程序好得多,例如:
INSERT INTO good_times VALUES (
UNIX_TIMESTAMP(CONVERT_TZ("2014-12-03 12:24:54", '+00:00', @@global.time_zone))
);
选择:
$statement = $myDB->prepare('INSERT INTO good_times VALUES (?)');
$statement->execute([$someTime->getTimestamp()]);
有些技术可以过滤相对时间(在过去30天内选择帖子,找到在注册后10分钟内购买的用户),超出了此范围。
答案 37 :(得分:0)
drop table if exists #ReceivingLog, #Customer_Event
go
create table #ReceivingLog
(
logId int,
eventId int,
customerId int,
pmCount int,
pmWeight int
);
go
insert into #ReceivingLog values
(1, 1411, 4196, 1, 14)
, (2, 1411, 4196, 2, 14)
, (3, 1411, 4198, 1, 14)
, (4, 1411, 4198, 1, 11)
, (5, 1411, 4196, 3, 10)
go
create table #Customer_Event
(
customerId int,
eventId int
);
go
insert into #Customer_Event values
(4196, 1411)
, (4198, 1411)
, (4199, 1411)
go
select c.customerId
, coalesce(sum(r.pmCount), 0) as SumOfPmCount
, coalesce(sum(r.pmWeight), 0) as SumOfPmWeight
from #Customer_Event c
left
join #ReceivingLog r
on c.customerId = r.customerId
and c.eventid = r.eventid
and c.eventid = 1411
group
by c.customerId
go
是计算机通过网络时间协议(NTP)记录的事件的当前时间。
timestamp
是在您的 PHP 配置中设置的当前时区。
答案 38 :(得分:0)
DATETIME vs TIMESTAMP:
TIMESTAMP用于跟踪记录的更改,并在每次记录更改时进行更新。
DATETIME用于存储不受记录更改影响的特定和静态值。
TIMESTAMP还受与TIME ZONE相关的其他设置的影响。 DATETIME是常数。
TIMESTAMP在内部将当前时区转换为UTC进行存储,并在检索过程中将其转换回当前时区。
DATETIME无法做到这一点。
TIMESTAMP是4个字节,DATETIME是8个字节。
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′