Date,Time和DateTime类是否必要?

Rya*_*wis 34 ruby

当有一个可以同时处理这两个类的类时,拥有DateTime类的目的是什么DateTime

And*_*Vit 43

总结一下常见的ruby时间类:

Time

这是核心红宝石时间类的基本主力.

  • 有日期和时间属性(年,月,日,小时,分钟,秒,秒)
  • 基于unix时代的浮点秒间隔(1970-01-01)
  • 在unix时代之前可以处理负面时间
  • 可以以秒为单位处理时间算术
  • 本机工作在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
Run Code Online (Sandbox Code Playgroud)

最后两个看起来很相似,但要注意:你不应该用非本地时间算术.这只是一个UTC偏移而没有区域的时间,所以它不知道DST的规则.在DST边界上添加时间不会改变偏移量,因此产生的时间将是错误的.

ActiveSupport::TimeWithZone

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

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

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

Date

  • 仅具有日期属性(年,月,日)
  • 基于任意"零日"的整数全天间隔(-4712-01-01)
  • 可以以整天为单位处理日期算术
  • 可以将古代朱利安历法中的日期转换为现代格里高利历

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

DateTime

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

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

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)
Run Code Online (Sandbox Code Playgroud)

此外,它具有无意义的"区域"属性(请注意非本地时间对象如何警告您zone == nil),并且在将其首先转换为时间之前,您无法了解其他任何内容:

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'
Run Code Online (Sandbox Code Playgroud)

处理微秒来检查舍入也有点奇怪.你会认为因为它没有一个usec属性只能处理整数,但你错了:

DateTime.now.usec # => NoMethodError: undefined method `usec'
DateTime.now.to_time.usec => 629399
Run Code Online (Sandbox Code Playgroud)

简而言之,除非您在古代过去处理天文事件并且需要将朱利安日期(一天中的时间)转换为现代日历,否则请不要使用DateTime.如果有人有这个课程的实际用例,我很乐意阅读你的评论.

  • @PauloCasaretto如果你从stdlib'需要'时间',那么它会将'Time#strptime`添加到核心Time类.(不知道为什么会这样.) (3认同)
  • 不要使用DateTime.此外,我在时区的rubyconf 2012上发表了闪电般的演讲,然后去查看我的笔记并看到"TODO:Date vs. Time vs. DateTime".https://gist.github.com/3668333 https://github.com/bf4/Notes/blob/master/talks_mine/time-lightning-rubyconf2012.pdf?raw=true http://vimeo.com/53892354 (2认同)

ste*_*lag 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
Run Code Online (Sandbox Code Playgroud)

结果:

                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)
Run Code Online (Sandbox Code Playgroud)

(Ruby 1.9.2)

  • 是的,科学!! (2认同)
  • 2.0中的日期和日期时间没有区别 (2认同)

saw*_*awa 17

DateTime是一个子类Date,所以无论你做什么Date都可以完成DateTime.但正如tadman和steenslag指出的那样,DateTime速度较慢.请参阅steenslag的答案,了解它的速度有多慢.

关于DateTimevs,Time我在这里找到了一些东西.

引文


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.
Run Code Online (Sandbox Code Playgroud)

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

  • "日期"也很有用,因为它没有任何相关的时区信息,这些信息可能会使一些计算变得不必要. (4认同)
  • 这个答案不是已经过时了吗?从Ruby 2开始,Time使用了来自epoch的63位,几乎可以在任何日期范围内使用.此外,DateTime不包括闰秒(与原子振荡和地球自转的差异),具有讽刺意味的是今天将于2015年6月30日星期二进行. (4认同)
  • 一般来说,不应该首选DateTime.请注意,您不能使用DateTime进行任何时间算术,因为它实际上只是一个添加了时间属性的日期.它只在整天处理:`DateTime.new(2012,12,31,0,0,0)+ 1 == DateTime.new(2013,1,1)` (3认同)
  • 日期并不关心时区,它甚至不知道它们是什么.将Date转换为DateTime,反之亦然,将使用时区,但您需要将其指定为默认设置或故意请求. (2认同)