在Ruby on Rails中,DateTime、Timestamp、Time和Date有什么区别?

462

在我的经验中,编程时正确处理日期/时间总是充满危险和困难。

对我来说,Ruby和Rails一直是个难题,因为它们提供了很多选项;我从不知道该选择哪一个。

当我使用Rails并查看ActiveRecord数据类型时,我可以找到以下几种:

:datetime、:timestamp、:time和:date

但我不知道它们之间的区别或可能存在的问题。

它们的区别是什么?你如何使用它们?

(注:我正在使用Rails3)


我认为混淆的部分在于 ActiveRecord 类型与 Ruby 类型不对应(例如 DateTime),而 Rails 层在其上甚至添加了其他类型(例如 TimeWithZone)。 - Christopher Oezbek
3个回答

634
ActiveRecord中不同日期/时间格式的区别与Rails无关,而与您所使用的数据库有关。以MySQL为例(因为它最受欢迎),您有DATE、DATETIME、TIME和TIMESTAMP列数据类型;就像您有CHAR、VARCHAR、FLOAT和INTEGER一样。那么,您可能会问,有什么区别?嗯,其中一些是不言自明的。DATE仅存储日期,TIME仅存储每天的时间,而DATETIME则同时存储两者。 DATETIMETIMESTAMP之间的区别有些微妙: DATETIME格式为YYYY-MM-DD HH:MM:SS。有效范围从1000年到9999年(以及其中的每一年)。虽然当您从数据库中获取TIMESTAMP时,它看起来很相似,但它实际上只是unix timestamp的一个前端。其有效范围从1970年到2038年。除了数据库引擎内的各种内置函数之外,这里的区别在于存储空间。因为DATETIME存储年、月、日、小时、分钟和秒中的每个数字,所以它总共使用8个字节。由于TIMESTAMP仅存储自1970-01-01以来的秒数,因此它使用4个字节。
您可以在MySQL here阅读更多关于时间格式之间的差异。
最终,它取决于您需要您的日期/时间列做什么:
  • 是否需要存储1970年之前或2038年之后的日期和时间? => 使用 DATETIME
  • 是否需要考虑数据库大小并且在该时间范围内? => 使用 TIMESTAMP
  • 是否只需存储日期? => 使用 DATE
  • 是否只需存储时间? => 使用 TIME

说了这么多,Rails实际上已经为你做出了一些决策。无论是 :timestamp 还是 :datetime,默认都使用 DATETIME,而 :date:time 分别对应于 DATETIME

这意味着在Rails中,你只需要决定是否需要存储日期、时间或两者都需要即可。


8
记录一下,我更喜欢使用绝对时间戳(Unix时间戳),因为YYYY-MM-DD格式依赖于所使用的时区。因此客户端需要知道服务器的时区,并进行转换。而秒级别的绝对时间戳不存在这个问题。 - n13
37
@n13 提出了一个好观点,但在Rails中并不是真正的问题,因为它在将日期时间插入数据库之前会将其转换为UTC。 - vonconrad
16
这是Rails领域中最有用的帖子之一。应该将它添加到Rails指南中... - Andrew
6
MySQL的TIME列不仅仅是严格意义上的“一天中的时间”,因为它可以接受大于24小时的数值,也可用作“经过的时间”。 - nickgrim
6
其他的数据库(比如PostgreSQL)是否也是这样的呢? - Andy Hayden
显示剩余5条评论

36
  1. :datetime (8 bytes)

    • 存储日期和时间,格式为YYYY-MM-DD HH:MM:SS
    • 适用于出生日期等列
  2. :timestamp (4 bytes)

    • 存储自1970年01月01日以来的秒数
    • 适用于更新时间和创建时间等列
  3. :date (3 bytes)
    • 存储日期
  4. :time (3 bytes)
    • 存储时间

5
这更像是上面被接受的答案的 TL:DR 版本。 - Chidozie Nnachor

3

我发现下面这篇文章对于时间戳和日期时间的解释十分准确:

时间戳(TIMESTAMP)用于跟踪记录的更改,并在记录更改时每次更新。日期时间(DATETIME)用于存储特定且静态的值,该值不受记录中任何更改的影响。

时间戳还受到与不同时区相关的设置的影响。日期时间是恒定的。

时间戳内部将当前时区转换为协调世界时(UTC)进行存储,并在检索期间将其转换回当前时区。日期时间无法实现此功能。

时间戳占4个字节,而日期时间占8个字节。

时间戳支持范围:从“1970-01-01 00:00:01” UTC到“2038-01-19 03:14:07” UTC。日期时间支持范围:从“1000-01-01 00:00:00”到 “9999-12-31 23:59:59”。

来源:https://www.dbrnd.com/2015/09/difference-between-datetime-and-timestamp-in-mysql/#:~:text=DATETIME%20vs%20TIMESTAMP%3A,DATETIME%20is%20constant

此外...

以下是不同列“日期”类型以及根据数据库相应的Rails迁移类型的表格


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接