有了能同时处理日期和时间的 DateTime
类,为什么还要有 Date
和 Time
两个类呢?
总结一下常见的 Ruby 时间类:
Time
这是基本的核心 Ruby 时间类。
实际上,当涉及到处理时区时,有三种不同类型的 Time 对象,让我们看一个夏令时的例子来展示 DST:
utc = Time.utc(2012,6,1) # => 2012-12-21 00:00:00 UTC
utc.zone # => "UTC"
utc.dst? # => false
utc.utc? # => true
utc.utc_offset # => 0
local = Time.local(2012,6,1) # => 2012-06-01 00:00:00 -0700
local.zone # => "PDT"
local.dst? # => true
local.utc? # => false
local.utc_offset # => -25200
nonlocal = Time.new(2012,6,1,0,0,0, "-07:00") # => 2012-06-01 00:00:00 -0700
nonlocal.zone # => nil
nonlocal.dst? # => false
nonlocal.utc? # => false
nonlocal.utc_offset # => -25200
最后两种类型看起来很相似,但要注意:不应该对非本地时间进行算术运算。它仅仅是带有UTC偏移量而没有时区的时间,因此不知道夏令时的规则。在夏令时的边界上添加时间不会改变偏移量,并且所得到的时间将是错误的。Time.new(2012, 12, 31, 0, 0, 0) + 1 == Time.new(2012, 12, 31, 0, 0, 1)
DateTime.new(2012, 12, 31, 0, 0, 0) + 1 == DateTime.new(2013, 1, 1, 0, 0, 0)
此外,它具有毫无意义的“zone”属性(请注意非本地时间对象会警告您zone == nil
),在将其转换为Time之前,您无法了解任何其他信息:
dt = DateTime.new(2012,12,6, 1, 0, 0, "-07:00")
dt.zone # => "-07:00"
dt.utc? # => NoMethodError: undefined method `utc?'
dt.dst? # => NoMethodError: undefined method `dst?'
dt.utc_offset # => NoMethodError: undefined method `utc_offset'
处理微秒来进行四舍五入的方式也有些奇怪。你可能会认为,由于它没有usec
属性,它只涉及整数,但你会发现这是错误的:
DateTime.now.usec # => NoMethodError: undefined method `usec'
DateTime.now.to_time.usec => 629399
简而言之,除非你处理古代的天文事件并需要将朱利安日历(含时间)转换为现代日历,否则请不要使用DateTime。如果有人真正需要使用这个类,请在评论中留言。
我知道已有一个被接受的答案,但我有一些要补充的。Date类是一个重量级、学术性强的类。它可以处理各种RFC,解析最奇怪的东西,并将来自千年前的儒略日转换为所选的格里高利改革日期。Time类则是轻量级的,不知道这些东西。它更便宜,在基准测试中有所体现:
require 'benchmark'
require 'date'
Benchmark.bm(10) do |x|
x.report('date'){100000.times{Date.today} }
x.report('datetime'){100000.times{DateTime.now} }
x.report('time'){100000.times{Time.now} }
end
结果:
user system total real
date 1.250000 0.270000 1.520000 ( 1.799531)
datetime 6.660000 0.360000 7.020000 ( 7.690016)
time 0.140000 0.030000 0.170000 ( 0.200738)
(Ruby 1.9.2)
DateTime
是Date
的子类,因此您可以使用Date
做的任何事情都可以使用DateTime
完成。但是,正如tadman和steenslag指出的那样,DateTime
速度较慢。有关它有多慢,请参见steenslag的答案。
关于DateTime
与Time
的区别,我在这里找到了一些内容here:
时间是Unix纪元的包装器。 日期(和DateTime)使用有理数和“零日”进行存储。因此,时间更快,但上限和下限与时期时间绑定(对于32位时期时间而言,大约是1970-2040...而日期(和DateTime)具有几乎无限的范围,但速度非常慢。
简而言之,DateTime
是全能巨星,并且通常应该优先使用,但如果想要最后一点优化,则使用Time
可以提高性能。
DateTime.new(2012,12,31,0,0,0) + 1 == DateTime.new(2013,1,1)
。 - Andrew VitDate
和DateTime
以时钟和日历的形式来模拟时间,这对于向用户描述时间和安排事件非常有用。如果您不关心时间并且不想考虑时区,那么只使用Date
而不涉及时间是很好的选择。
Time
将时间建模为一个连续体,并包装Unix时间戳(仅为整数)。这对计算机内部应用程序非常有用,因为它们不太关心是否跨越了日历边界,而只关心经过了多少秒(或毫秒)。是的。Date仅处理某些日期,例如1989年3月31日。但它不处理时间,例如下午12:30。 DateTime可以同时处理日期和时间,例如1989年3月31日下午12:30 EST。
有时您不需要DateTime的所有部分。例如,您想知道用户何时注册了您的网站,这里使用Date就足够了,因为时间最终是无关紧要的。
在某些情况下,您可能只想要时间。例如,如果是午餐时间,您可能想告诉用户您的办公室已关闭。此时,日期是无关紧要的。
然而,在大多数情况下,使用DateTime,因为它可以用作日期、时间或两者兼备。
DateTime
的用途...一个日历/调度应用程序,允许用户创建重复预约,在跨越夏令时边界时应该出现在所选的时间。最简单的方法是使用一个不知道夏令时的类来实现。 - Alex DTime.new(,,,,,,"-08:00")
,它提供了一个UTC偏移量但忽略了夏令时。无论哪种情况,你都必须注意UTC偏移量在一年中有一半是错误的,因此与实际时间(如“现在”)进行比较可能是错误的。 - Andrew Vitrequire 'time'
,则会将Time#strptime
添加到核心的Time类中。(不确定为什么会是这样。) - Andrew Vit