3

在测试一些 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
4

3 回答 3

3

我会尝试“解释你所看到的”。以下是时间值的几个比较,以及在不同格式之间转换时会发生什么。我不打算进行任何相等性检查,因为您只需查看一个值就可以知道它是否应该匹配:

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"

只要值的整数部分完好无损,正常inspect和输出不会显示任何精度差异。to_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
于 2013-04-05T03:03:01.163 回答
2

小数秒不同:

>> 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
于 2013-04-05T00:27:50.507 回答
1

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

尝试:

t.to_f == i.to_f

我想你会看到它t比它更精确i

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

于 2013-04-05T00:01:20.860 回答