Tom*_*man 216 ruby time datetime
什么之间的区别DateTime,并Time在Ruby类与哪些因素会导致我选择一个或其他?
tad*_*man 176
较新版本的Ruby(2.0+)在两个类之间并没有真正的显着差异.由于历史原因,一些图书馆将使用其中一个,但新代码不一定需要关注.选择一个以保持一致性可能是最好的,因此请尝试与您的库所期望的相匹配.例如,ActiveRecord更喜欢DateTime.
在Ruby 1.9之前的版本中以及许多系统上,Time表示为32位有符号值,描述自1970年1月1日UTC以来的秒数,这是一个围绕POSIX标准time_t值的薄包装,并且有界:
Time.at(0x7FFFFFFF)
# => Mon Jan 18 22:14:07 -0500 2038
Time.at(-0x7FFFFFFF)
# => Fri Dec 13 15:45:53 -0500 1901
Run Code Online (Sandbox Code Playgroud)
较新版本的Ruby能够处理更大的值而不会产生错误.
DateTime是一种基于日历的方法,其中单独存储年,月,日,小时,分钟和秒.这是一个Ruby on Rails构造,用作SQL标准DATETIME字段的包装器.这些包含任意日期,几乎可以表示任何时间点,因为表达范围通常非常大.
DateTime.new
# => Mon, 01 Jan -4712 00:00:00 +0000
Run Code Online (Sandbox Code Playgroud)
因此,令人放心的是,DateTime可以处理来自亚里士多德的博客文章.
选择一个时,差异在某种程度上是主观的.从历史上看,DateTime提供了以日历方式操作它的更好选项,但是其中许多方法也已移植到Time,至少在Rails环境中.
Nie*_*ser 97
[编辑2018年7月]
以下所有内容在Ruby 2.5.1中仍然适用.从参考文档:
DateTime不考虑任何闰秒,不跟踪任何夏令时规则.
之前在这个帖子中没有注意到的是以下几个优点之一DateTime:它知道日历改革而Time不是:
[...] Ruby的时间类实现了一个预感格里高利历,并没有日历改革的概念[...].
参考文档最后提出了Time在专门处理近期,当前或未来日期/时间时使用的建议,仅DateTime在莎士比亚的生日需要准确转换时使用:(强调添加)
那么什么时候应该在Ruby中使用DateTime以及何时应该使用Time?几乎可以肯定你会想要使用Time,因为你的应用可能正在处理当前的日期和时间.但是,如果您需要在历史上下文中处理日期和时间,则需要使用DateTime [...].如果你还需要处理时区,那么祝你好运 - 请记住,你可能会处理当地的太阳时代,因为直到19世纪铁路的引入才需要标准时间并最终时区.
[/编辑2018年7月]
从ruby 2.0开始,其他答案中的大部分信息都已过时.
特别是,Time现在几乎没有约束力.它可以比Epoch更多或更少甚至63位:
irb(main):001:0> RUBY_VERSION
=> "2.0.0"
irb(main):002:0> Time.at(2**62-1).utc # within Integer range
=> 146138514283-06-19 07:44:38 UTC
irb(main):003:0> Time.at(2**128).utc # outside of Integer range
=> 10783118943836478994022445751222-08-06 08:03:51 UTC
irb(main):004:0> Time.at(-2**128).utc # outside of Integer range
=> -10783118943836478994022445747283-05-28 15:55:44 UTC
Run Code Online (Sandbox Code Playgroud)
使用较大值的唯一结果应该是性能,这Integer在使用Bignums 时更好(相对于s(超出Integer范围的值)或Rationals(跟踪纳秒)):
从Ruby 1.9.2开始,Time实现使用带符号的63位整数,Bignum或Rational.整数是自Epoch以来的纳秒数,可以代表1823-11-12到2116-02-20.当使用Bignum或Rational时(在1823之前,在2116之后,在纳秒之下),时间比使用整数时更慢.(http://www.ruby-doc.org/core-2.1.0/Time.html)
换句话说,据我所知,DateTime不再涵盖更广泛的潜在价值Time.
此外,DateTime应该注意两个先前未提及的限制:
DateTime不考虑任何跳跃,不跟踪任何夏令时规则.(http://www.ruby-doc.org/stdlib-2.1.0/libdoc/date/rdoc/Date.html#class-Date-label-DateTime)
首先,DateTime没有闰秒的概念:
irb(main):001:0> RUBY_VERSION
=> "2.0.0"
irb(main):002:0> require "date"
=> true
irb(main):003:0> t = Time.new(2012,6,30,23,59,60,0)
=> 2012-06-30 23:59:60 +0000
irb(main):004:0> dt = t.to_datetime; dt.to_s
=> "2012-06-30T23:59:59+00:00"
irb(main):005:0> t == dt.to_time
=> false
irb(main):006:0> t.to_i
=> 1341100824
irb(main):007:0> dt.to_time.to_i
=> 1341100823
Run Code Online (Sandbox Code Playgroud)
其次,Time对时区的理解非常有限,特别是没有夏令时的概念.它几乎将时区作为简单的UTC + X偏移处理:
irb(main):001:0> RUBY_VERSION
=> "2.0.0"
irb(main):002:0> require "date"
=> true
irb(main):003:0> t = Time.local(2012,7,1)
=> 2012-07-01 00:00:00 +0200
irb(main):004:0> t.zone
=> "CEST"
irb(main):005:0> t.dst?
=> true
irb(main):006:0> dt = t.to_datetime; dt.to_s
=> "2012-07-01T00:00:00+02:00"
irb(main):007:0> dt.zone
=> "+02:00"
irb(main):008:0> dt.dst?
NoMethodError: undefined method `dst?' for #<DateTime:0x007f34ea6c3cb8>
Run Code Online (Sandbox Code Playgroud)
当时间输入DST然后转换为非DST时区而不跟踪其TZ=right/UTC irb自身之外的正确偏移时,这可能会导致麻烦(许多操作系统实际上可能已经为您处理了这个问题).
总的来说,我认为现在DateTime是大多数应用程序的更好选择.
另请注意添加的重要区别:当您向Time对象添加数字时,它会以秒为单位计算,但是当您向DateTime添加数字时,它会以天为单位计算.
Mla*_*vić 66
过时!见下文...
性能差异不够强调......时间是C,而DateTime是Ruby:
>> Benchmark.bm do |bm|
?> bm.report('DateTime:') do
?> n1 = DateTime.now
>> n2 = DateTime.now
>> 1_000_000.times{ n1 < n2 }
>> end
>> bm.report('Time: ') do
?> n1 = Time.now
>> n2 = Time.now
>> 1_000_000.times{ n1 < n2 }
>> end
>> end
user system total real
DateTime: 4.980000 0.020000 5.000000 ( 5.063963)
Time: 0.330000 0.000000 0.330000 ( 0.335913)
Run Code Online (Sandbox Code Playgroud)
更新(2012年2月):
正如评论中已经提到的,1.9.3大大提高了DateTime性能:
user system total real
DateTime: 0.330000 0.000000 0.330000 ( 0.333869)
Time: 0.300000 0.000000 0.300000 ( 0.306444)
Run Code Online (Sandbox Code Playgroud)
Rhu*_*arb 43
我认为"有什么不同"的答案是Ruby标准库中这个问题的一个不幸的常见答案:两个类/库是由不同的人在不同时间创建的.与精心策划的Java开发相比,这是Ruby发展的社区性质的不幸后果之一.开发人员需要新的功能,但不想踩到现有的API,因此他们只是创建一个新类 - 对于最终用户来说,没有明显的理由让这两个存在.
对于一般的软件库来说也是如此:通常,某些代码或API的结果是历史而非逻辑.
诱惑是从DateTime开始,因为它似乎更通用.日期......和时间,对吧?错误.时间也更好地更新日期,实际上可以解析DateTime不能的时区.它也表现得更好.
我到处都在使用Time.
为了安全起见,我倾向于允许将DateTime参数传递给我的Timey API,并进行转换.另外,如果我知道两者都有我感兴趣的方法,我也接受,就像我写的用于将时间转换为XML(用于XMLTV文件)的方法
# Will take a date time as a string or as a Time or DateTime object and
# format it appropriately for xmtlv.
# For example, the 22nd of August, 2006 at 20 past midnight in the British Summertime
# timezone (i.e. GMT plus one hour for DST) gives: "20060822002000 +0100"
def self.format_date_time(date_time)
if (date_time.respond_to?(:rfc822)) then
return format_time(date_time)
else
time = Time.parse(date_time.to_s)
return format_time(time)
end
end
# Note must use a Time, not a String, nor a DateTime, nor Date.
# see format_date_time for the more general version
def self.format_time(time)
# The timezone feature of DateTime doesn't work with parsed times for some reason
# and the timezone of Time is verbose like "GMT Daylight Saving Time", so the only
# way I've discovered of getting the timezone in the form "+0100" is to use
# Time.rfc822 and look at the last five chars
return "#{time.strftime( '%Y%m%d%H%M%S' )} #{time.rfc822[-5..-1]}"
end
Run Code Online (Sandbox Code Playgroud)
Yur*_*nko 10
假设您正在使用ActiveSupport扩展,我发现使用DateTime解析和计算不同时区的一天开始/结束等事情更容易.
在我来说,我需要在此基础上我作为一个字符串接收到用户的本地时间,如"2012年10月10日10:10 +0300"计算一天结束在用户的时区(任意)
使用DateTime就像它一样简单
irb(main):034:0> DateTime.parse('2012-10-10 10:10 +0300').end_of_day
=> Wed, 10 Oct 2012 23:59:59 +0300
# it preserved the timezone +0300
Run Code Online (Sandbox Code Playgroud)
现在让我们以与时间相同的方式尝试:
irb(main):035:0> Time.parse('2012-10-10 10:10 +0300').end_of_day
=> 2012-10-10 23:59:59 +0000
# the timezone got changed to the server's default UTC (+0000),
# which is not what we want to see here.
Run Code Online (Sandbox Code Playgroud)
实际上,Time需要在解析之前知道时区(也请注意它Time.zone.parse,而不是Time.parse):
irb(main):044:0> Time.zone = 'EET'
=> "EET"
irb(main):045:0> Time.zone.parse('2012-10-10 10:10 +0300').end_of_day
=> Wed, 10 Oct 2012 23:59:59 EEST +03:00
Run Code Online (Sandbox Code Playgroud)
所以,在这种情况下,使用DateTime肯定更容易.
除了Niels Ganser 的回答之外,您还可以考虑以下论点:
\n\n请注意,《Ruby 风格指南》非常清楚地表明了对此的立场:
\n\n\n\n无日期时间
\n\n不要\xe2\x80\x99t 使用 DateTime,除非您需要考虑历史日历改革 - 如果需要,请显式指定开始参数以\n 清楚地说明您的意图。
\n\nRun Code Online (Sandbox Code Playgroud)\n# bad - uses DateTime for current time\nDateTime.now\n\n# good - uses Time for current time\nTime.now\n\n# bad - uses DateTime for modern date\nDateTime.iso8601(\'2016-06-29\')\n\n# good - uses Date for modern date\nDate.iso8601(\'2016-06-29\')\n\n# good - uses DateTime with start argument for historical date\nDateTime.iso8601(\'1751-04-23\', Date::ENGLAND)\n