x6iae
x6iae

Reputation: 4164

parsing string to time is not the same as the original time

So I was having a problem with finding records by using one of the object property which is of class Time.

Turns out that when I pass in the time as a params to my controller, which in turn sends it to the model... the time object I'm sending gets stringified.

So I thought I will just convert it back to Time either by Time.parse(<stringified time>) or <stringified time>.to_time - (Using rails)

But my test keeps failing, so I decided to do some look into what was going on there.

This was what I found out:

2.2.0 :003 > a = Time.now
 => 2015-10-14 20:50:19 +0100 
2.2.0 :004 > b = a.to_s
 => "2015-10-14 20:50:19 +0100" 
2.2.0 :005 > c = Time.parse b
 => 2015-10-14 20:50:19 +0100 
2.2.0 :006 > c == a
 => false 
2.2.0 :007 > a.class
 => Time 
2.2.0 :008 > c.class
 => Time 
2.2.0 :015 > a - c
 => 0.951439 
2.2.0 :016 > d = b.to_time
 => 2015-10-14 20:50:19 +0100 
2.2.0 :017 > c - d
 => 0.0 

My confusion is mostly from the line: a - c which gave me 0.951439. Where did this difference come from?

Most importantly, how do I make these two to be equal? Thanks much, all.

Upvotes: 2

Views: 117

Answers (1)

Arsen
Arsen

Reputation: 10951

The reason:

Since Ruby 1.9.2, Time implementation uses a signed 63 bit integer, Bignum or Rational. The integer is a number of nanoseconds since the Epoch which can represent 1823-11-12 to 2116-02-20. When Bignum or Rational is used (before 1823, after 2116, under nanosecond), Time works slower as when integer is used.

And if you run a = Time.now you got N seconds since the Epoch plus P nanoseconds. But when you run Time.parse b you got same number seconds but with zero nanosecond. This is what you're looking for.

Loading development environment (Rails 4.2.4)
[1] pry(main)> a = Time.now
=> 2015-10-14 23:41:12 +0300
[2] pry(main)> a.nsec
=> 733355000
[3] pry(main)> Time.parse(a.to_s).nsec
=> 0

So you have to avoid this nano stuff. For instance you can write something like that:

[16] pry(main)> a = Time.at(Time.now.to_i)
=> 2015-10-14 23:47:59 +0300
[17] pry(main)> a.nsec
=> 0

Upvotes: 2

Related Questions