Date,Time和DateTime类是否必要?

时间:2011-05-09 19:37:53

标签: ruby

如果有Date类可以同时处理这两个类,那么拥有TimeDateTime类的目的是什么?

5 个答案:

答案 0 :(得分:43)

总结常见的红宝石时间类:

Time

这是基本的主力核心红宝石时间等级。

  • 具有日期和时间属性(年,月,日,小时,分钟,秒,秒)
  • 基于unix epoch(1970-01-01)的浮点秒间隔
  • 可以在unix epoch之前处理负面时间
  • 可以以秒为单位处理时间算术
  • 本地使用UTC或“本地”(系统时区)

在处理时区时,确实有3种时间对象,让我们来看夏季时间来显示夏令时:

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偏移而没有区域的时间,所以它不知道DST的规则。在DST边界上添加时间不会改变偏移量,并且生成的时间将是错误的。

ActiveSupport::TimeWithZone

这个值得一提,因为它是你在Rails中使用的。与时间相同,加上:

  • 可以处理任何时区
  • 尊重DST
  • 可以在区域之间转换时间

当ActiveSupport可用时,我通常总能达到这个目的,因为它可以处理所有时区陷阱。

Date

  • 仅限日期属性(年,月,日)
  • 基于来自任意“第0天”(-4712-01-01)
  • 的整数全天间隔
  • 可以以全天为单位处理日期算术
  • 可以将古代儒略历中的日期转换为现代格里高利

每当你整天交易时,日期比时间更有用:没有时区可以担心! (我很惊讶这不涉及现代波斯日历,因为它知道几个世纪前过时的朱利安历法。)

DateTime

  • 具有日期和时间属性(年,月,日,小时,分钟,秒)
  • 基于来自任意“第0天”(-4712-01-01)
  • 的全天间隔的分数
  • 可以以整天或分数为单位处理日期算术

就个人而言,我从不有理由使用它:它很慢,它处理时间而不考虑时区,并且它具有不一致的界面。每当你假设你有一个类似时间的对象时,我发现它会导致混乱,但实际上的行为类似于日期

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 == nil),并且在将其转换为时间之前您无法了解其他任何内容:< / p>

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。如果有人有这个课程的实际用例,我很乐意阅读你的评论。

答案 1 :(得分:28)

我知道有一个已接受的答案,但我有一些要补充的内容。 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)

答案 2 :(得分:17)

DateTimeDate的子类,因此Date可以使用DateTime完成任何操作。但正如tadman和steenslag指出的那样,DateTime更慢。请参阅steenslag的答案,了解它的速度有多慢。

关于DateTime vs,Time,我发现了一些here

<强>引用


Time is a wrapper around Unix-Epoch.
Date (and DateTime) use rational and a "day zero" for storage. So Time 
is faster but the upper and lower bounds are tied to epoch time (which 
for 32bit epoch times is something around 1970-2040 ... while Date (and DateTime) have an 
almost infinite range but are terribly slow.

简而言之,DateTime是一个全能的超级巨星,一般应该是首选,但如果你想优化到最后一位,使用Time可以提高性能。

答案 3 :(得分:4)

另一种思考方式是DateDateTime在时钟和日历方面的模型时间,这对于向用户描述时间和调度事件很有用。如果你不关心时间,那么Date没有时间是很好的,你不想考虑时区。

Time将时间建模为连续体,并且是Unix时间戳的包装器,它只是一个整数。这对于各种内部应用程序非常有用,在这些应用程序中,计算机并不关心是否已经越过日历边界,而是已经过了多少秒(或毫秒)。

答案 4 :(得分:-1)

是。日期仅处理某事物的日期,即I.E.,1989年3月31日。但它不处理时间,例如,下午12:30。 DateTime,可以处理1989年3月31日美国东部时间下午12:30。

有时您不需要DateTime的所有部分。例如,您想知道何时使用该网站注册,Date在这里很有用,因为时间最终无关紧要。

在某些情况下,您可能只想要时间。例如,如果是午餐时间,您可能想告诉用户您的办公室已关闭。此时,数据无关紧要。

但是,在大多数情况下使用DateTime,因为它可以用作日期,时间或两者。