Bug #2952
closedTime.strftime format %N
Description
=begin
There seems to be some rouding errors with the %N formatter for Time->strftime
t1 = 1236922275.8516
t2 = Time.at(t1)
puts t1
puts t2.to_f
puts t1 == t2.to_f
puts t2.strftime("%s.%6N")
prints
1236922275.8516
1236922275.8516
true
1236922275.851599
The last line is wrong. I would expect it would print "1236922275.851600".
If I use %4N I get 1236922275.8515 which is also wrong
=end
Updated by shugo (Shugo Maeda) about 14 years ago
=begin
There seems to be some rouding errors with the %N formatter for Time->strftime
t1 = 1236922275.8516
t2 = Time.at(t1)
It is because a Float can't represent 1236922275.8516 exactly, isn't it?
The following script prints "1236922275.851600".
$ cat t.rb
t = Time.at(1236922275, 851600)
puts t.strftime("%s.%6N")
$ ruby-trunk -v t.rb
ruby 1.9.2dev (2010-03-10 trunk 26866) [i686-linux]
1236922275.851600
=end
Updated by naruse (Yui NARUSE) about 14 years ago
- Status changed from Open to Rejected
=begin
Use Rational as following:
t1 = Rational("1236922275.8516")
t2 = Time.at(t1)
puts t2.to_r
puts t1 == t2.to_r
=end
Updated by rpenney (Russell Penney) about 14 years ago
=begin
Firstly to_r is not defined for Time at least in 1.9.1
Also try
t = Time.at(1236922275, 8516)
puts t.strftime("%s.%6N")
it prints
1236922275.008516
which is wrong. It should be 1236922275.851600
=end
Updated by rpenney (Russell Penney) about 14 years ago
=begin
Also if a Float can't represent 1236922275.8516 exactly, how does "puts t1" work to print the exact value? I would expect it would print the same value that %N does.
My point is that "puts t1" and strftime("%s.%N") give different values. They should not. One of them is wrong.
=end
Updated by matz (Yukihiro Matsumoto) about 14 years ago
=begin
Hi,
In message "Re: [ruby-core:28606] [Bug #2952] Time.strftime format %N"
on Thu, 11 Mar 2010 17:42:55 +0900, Russell Penney redmine@ruby-lang.org writes:
|t = Time.at(1236922275, 8516)
|puts t.strftime("%s.%6N")
|
|it prints
|1236922275.008516
|which is wrong. It should be 1236922275.851600
It's caused by Ruby compiled by certain version of GCC, try upgrade
the compiler.
matz.
=end
Updated by naruse (Yui NARUSE) about 14 years ago
=begin
(2010/03/11 17:42), Russell Penney wrote:
Issue #2952 has been updated by Russell Penney.
Firstly to_r is not defined for Time at least in 1.9.1
Ah, yes, it's a 1.9.2's feature.
Anyway, you may think 1236922275.8516 is 12369222758516/10000.
But actually it is floating point number,
so its true value is 5188028049293469/4194304.
When you get (5188028049293469/4194304).to_f will be
1236922275.8516.
Why this works is because precision of Ruby's Float is
16 decimal digits.
When you get %N, it is calculated by only less than one value;
in 1.9.2 words t2.subsec, it is (3571869/4194304).
this precision is counted from 0, so its precision is higher than
that of before.
So (3571869/4194304).to_f is 0.8515999317169189.
You may find that previous 0.8516 is a rounded value from 0.8515999.
Also try
t = Time.at(1236922275, 8516)
puts t.strftime("%s.%6N")it prints
1236922275.008516
which is wrong. It should be 1236922275.851600
It's correct.
Time#at's second argument is microsecond, and %6N is microsecond.
so 008516 is correct output.
You should try Time.at(1236922275, 851600).strftime("%N") and get:
=> "851600000"
--
NARUSE, Yui naruse@airemix.jp
=end
Updated by rpenney (Russell Penney) about 14 years ago
=begin
Thank you, that makes a lot of sense. I obviously had been looking at values that don't suffer from the Float precision (or round up to the same value) which is why I got confused with Float#to_s printing the same value.
I looked more closely at Time#at in the documents and saw it expects microseconds as you say, my bad.
=end