时间.now与Time生成的Time不匹配.parse或Time.at



在测试一些Ruby代码时,我遇到了一些奇怪的行为。有人能解释一下为什么Time.now不匹配从Time.at创建或从Time.parse解析的相同时间吗?

[1] pry(main)> require 'time'
=> true
[2] pry(main)> t = Time.now
=> 2013-04-04 19:46:49 -0400
[3] pry(main)> i = Time.at t.to_i
=> 2013-04-04 19:46:49 -0400
[4] pry(main)> t == i
=> false
[5] pry(main)> t.to_i == i.to_i
=> true
[6] pry(main)> p = Time.parse t.to_s
=> 2013-04-04 19:46:49 -0400
[7] pry(main)> t == p
=> false
[8] pry(main)> t.to_i == p.to_i
=> true
[8] pry(main)> t.class
=> Time
[9] pry(main)> i.class
=> Time
[10] pry(main)> p.class
=> Time
[11] pry(main)> t.inspect
=> "2013-04-04 19:46:49 -0400"
[12] pry(main)> i.inspect
=> "2013-04-04 19:46:49 -0400"
[13] pry(main)> p.inspect
=> "2013-04-04 19:46:49 -0400"

更新1

似乎即使尝试获得亚秒精度也会显示相同的行为:

[1] pry(main)> t = Time.now
=> 2013-04-04 20:04:47 -0400
[2] pry(main)> f = Time.at t.to_f
=> 2013-04-04 20:04:47 -0400
[3] pry(main)> t == f
=> false
[4] pry(main)> t.to_f
=> 1365120287.902954
[5] pry(main)> f.to_f
=> 1365120287.902954

我试着解释一下你所看到的。下面是Time值的几个比较,以及在不同格式之间转换时会发生什么。我不打算做任何相等性检查,因为您可以通过查看它来查看值是否应该匹配:

require 'time'                                         
t_now = Time.now # => 2013-04-04 20:10:17 -0700

这是inspect的输出,丢掉了大量的信息和精度。对于凡人来说,这已经足够好了。

t_now.to_f # => 1365131417.613106

这是计算机通常看到的值,以微秒为单位。

t_now.to_i # => 1365131417

这是同一时间,微秒都消失了。

Time.at(t_now)      # => 2013-04-04 20:10:17 -0700
Time.at(t_now.to_f) # => 2013-04-04 20:10:17 -0700
Time.at(t_now.to_i) # => 2013-04-04 20:10:17 -0700
t_now.to_s          # => "2013-04-04 20:10:17 -0700"

正常inspectto_s输出不会显示任何精度上的差异,只要值的整数部分是完整的。

Time.parse(t_now.to_s)      # => 2013-04-04 20:10:17 -0700
Time.parse(t_now.to_s).to_f # => 1365131417.0

解析会丢失解析,除非您提供一个包含小数时间的值并定义解析格式,以便strptime知道如何处理它。默认解析器格式是为通用而非高精度设计的,因此我们必须使用strftime而不是允许to_s以其方式处理值,并允许strptime了解所有这些数字的含义:

T_FORMAT = '%Y/%m/%d-%H:%M:%S.%N' # => "%Y/%m/%d-%H:%M:%S.%N"
t_now.strftime(T_FORMAT)          # => "2013/04/04-20:10:17.613106000"
Time.strptime(t_now.strftime(T_FORMAT), T_FORMAT).to_f # => 1365131417.613106

分数秒是不同的:

>> t = Time.now
=> 2013-04-04 17:34:34 -0700
>> f = Time.at(t.to_f)
=> 2013-04-04 17:34:34 -0700
>> t.usec
=> 571153
>> f.usec
=> 571152
>> t.nsec
=> 571153000
>> f.nsec
=> 571152925

很可能这两个时间实际上是不同的,但是你没有看到你选择的表示的差异。

试题:

t.to_f == i.to_f

我想你会发现ti更精确。

内部Time表示为浮点值,精度为亚秒级。通常情况下,你可以指望它精确到百万分之一秒,有时甚至更多取决于你的操作系统。

最新更新