Bug #10135
closedTime.at is inaccurate
Description
I believe I have found an issue with Time.at. Many runtimes and DBs use milliseconds since epoch for recording time. Currently, the only way to generate a Time in ruby with milliseconds is:
However, this is inaccurate:
> Time.at(1381089302195 / 1000.0).to_f
=> 1381089302.1949997
> Time.at(1381089302195 / 1000.0).strftime('%3N')
=> "194"
This doesn't make much sense because you would expect:
It seems that somewhere in the MRI, someone is using floating-point math to represent a Time.
Is there any other way (workaround) to construct Time with millisecond accuracy?
Updated by sawa (Tsuyoshi Sawada) almost 12 years ago
Updated by normalperson (Eric Wong) almost 12 years ago
Updated by naruse (Yui NARUSE) almost 12 years ago
- Related to Bug #10136: printf("%.60f\n", 0.1r) shows 0.100000000000000005551115123125782702118158340454101562500000 added
Updated by nobu (Nobuyoshi Nakada) almost 12 years ago
- Assignee changed from core to akr (Akira Tanaka)
- Priority changed from 5 to 3
1381089302.195 cannot be represented in binary format.
AFAIK, it should be a spec by akr that Time#strftime('%N') truncates but doesn't round.
Updated by david_macmahon (David MacMahon) almost 12 years ago
John Smart wrote:
I believe I have found an issue with Time.at. Many runtimes and DBs use milliseconds since epoch for recording time. Currently, the only way to generate a Time in ruby with milliseconds is:
Another (better) way is:
That passes the non-integer seconds as a Rational rather than a Float so precision is maintained:
>> Time.at(1381089302195.to_r / 1000).strftime('%N')
=> "195000000"
# Modern Ruby (since 2.x?) can use 'r' suffix for literal Rationals
>> Time.at(1381089302195r / 1000).strftime('%N')
=> "195000000"
It seems that somewhere in the MRI, someone is using floating-point math to represent a Time.
Actually, you were the one who started using floating point math to represent Time when you divided milliseconds by 1000.0! :-)
Updated by akr (Akira Tanaka) almost 12 years ago
- Status changed from Open to Rejected
John Smart wrote:
It seems that somewhere in the MRI, someone is using floating-point math to represent a Time.
You use floating point math in 1381089302195 / 1000.0 which is
1381089302.1949999332427978515625.
The Time instance contains the value and strftime('%3N') truncates digits
after 3 digits, as documented (with a reason).
Floating point math is not used except conversion from the given argument to
rational.
Is there any other way (workaround) to construct Time with millisecond accuracy?
You can use the rational or the second argument of Time.at as others explained.