Bug #2733

rubyspec: Time#+ rounds micro seconds rather than truncates FAILED

Added by mame (Yusuke Endoh) over 2 years ago. Updated about 1 year ago.

[ruby-dev:40384]
Status:Rejected Start date:
Priority:Low Due date:
Assignee:akr (Akira Tanaka) % Done:

0%

Category:core
Target version:1.9.2
ruby -v:ruby 1.9.1p243 (2009-07-16 revision 24175) [x86_64-linux]

Description

akr さん
遠藤です。

Evan Phoenix と Time の挙動について相談した上で Time について一応の
確認です。


- 1.8 の Time#+ は usec で四捨五入していますが、1.9 ではしません。
  内部表現が Rational になったのだから当然だと思いますが、仕様変更
  ですよね。

- 1.8 の Time#usec や nsec が四捨五入しないのは仕様ですよね。
  usec が 1000000 とかになったら嫌ですものね。


そうだよんと言ってくだされば、以下のコミットを rubyspec にコミット
しようと思います。


diff --git a/core/time/plus_spec.rb b/core/time/plus_spec.rb
index 1f5c85f..e333430 100644
--- a/core/time/plus_spec.rb
+++ b/core/time/plus_spec.rb
@@ -10,21 +10,33 @@ describe "Time#+" do
     (Time.at(1.1) + 0.9).should == Time.at(0.9) + 1.1
   end

-  it "rounds micro seconds rather than truncates" do
-    # The use of 8.9999999 is intentional. This is because
-    # Time treats the fractional part as the number of micro seconds.
-    # Thusly it multiplies the result by 1_000_000 to go from
-    # seconds to microseconds. That conversion should be rounded
-    # properly. In this case, it's rounded up to 1,000,000, and thus
-    # contributes a full extra second to the Time object.
-    t = Time.at(0) + 8.9999999
-    t.should == Time.at(9)
-    t.usec.should == 0
+  ruby_version_is "" ... "1.9" do
+    it "rounds micro seconds rather than truncates" do
+      # The use of 8.9999999 is intentional. This is because
+      # Time treats the fractional part as the number of micro seconds.
+      # Thusly it multiplies the result by 1_000_000 to go from
+      # seconds to microseconds. That conversion should be rounded
+      # properly. In this case, it's rounded up to 1,000,000, and thus
+      # contributes a full extra second to the Time object.
+      t = Time.at(0) + 8.9999999
+      t.should == Time.at(9)
+      t.usec.should == 0
+
+      # Check the non-edge case works properly, that the fractional part
+      # contributes to #usecs
+      t2 = Time.at(0) + 8.9
+      t2.usec.should == 900000
+    end
+  end

-    # Check the non-edge case works properly, that the fractional part
-    # contributes to #usecs
-    t2 = Time.at(0) + 8.9
-    t2.usec.should == 900000
+  ruby_version_is "1.9" do
+    it "does NOT round" do
+      t = Time.at(0) + Rational(8_999_999_999_999_999, 1_000_000_000_000_000)
+      t.should_not == Time.at(9)
+      t.usec.should == 999_999
+      t.nsec.should == 999_999_999
+      t.subsec.should == Rational(999_999_999_999_999, 1_000_000_000_000_000)
+    end
   end

   ruby_version_is "" ... "1.9" do

-- 
Yusuke ENDOH <mame@tsg.ne.jp>

History

Updated by mame (Yusuke Endoh) over 2 years ago

遠藤です。

2010年2月11日21:36 Tanaka Akira <akr@fsij.org>:
> 2010年2月11日2:58 Yusuke ENDOH <mame@tsg.ne.jp>:
>>
>> - 1.8 の Time#+ は usec で四捨五入していますが、1.9 ではしません。
>>  内部表現が Rational になったのだから当然だと思いますが、仕様変更
>>  ですよね。
>
> 1.9.2 ではそうです。
> 1.9.1 の内部表現は nsec 単位なので、nsec で四捨五入なんではないかと思います。
>
>> - 1.8 の Time#usec や nsec が四捨五入しないのは仕様ですよね。
>>  usec が 1000000 とかになったら嫌ですものね。
>
> 1.8 に nsec はありませんが、まぁそうならざるを得ないですかね。

ありがとうございます。コミットさせて頂きました。

ちなみに rubyspec は 1.9.1 の仕様を無視する方針らしいです (1.9.1 と
1.9.2 の間で仕様変更がありすぎだから) 。なので、1.9 と書いてあれば
1.9.2 以降を指すということです。


> 繰り上がる先がある場合はどうかなぁ。

個人的には切り捨てがわかりやすいのでそれでいいと思いますが、変える
なら変えてもらっても構わないです。rubyspec 側を修正します。

-- 
Yusuke ENDOH <mame@tsg.ne.jp>

Updated by kosaki (Motohiro KOSAKI) over 2 years ago

>> 個人的には切り捨てがわかりやすいのでそれでいいと思いますが、変える
>> なら変えてもらっても構わないです。rubyspec 側を修正します。
>
> 仕掛けがわかりやすいからといって結果がわかりやすいかというと
> 微妙なのではないかと。
>
> 切り捨てで処理するのは崖っぷちを歩くようなもので、
> ひとつ間違えると意図せざる結果になりがちです。
>
> とりあえず Time#round(ndigits) とかどうかなぁ。

Timeの元データは何があるんでしょう?一番苦情がくるのは oldtime > newtime または oldtime > now
になってしまうケースで、oldtimeが精度落とすときに切り上げされていてnowが高精度だったりすると
起こせそうな気がします。

個人的には切り捨てに一票で、理由は「え、思ってたよりちょっと古い時刻だった?そりゃ測定してるうちにも時間は
経過するからねHAHAHA」でほとんどのケースは済んでしまうコーナーケースの少なさに利点があるかと。

Updated by naruse (Yui NARUSE) over 2 years ago

  • Category set to core
  • Status changed from Open to Assigned
  • Assignee set to akr (Akira Tanaka)
  • Target version set to 1.9.2
  • ruby -v set to ruby 1.9.1p243 (2009-07-16 revision 24175) [x86_64-linux]

Updated by mame (Yusuke Endoh) about 2 years ago

  • Status changed from Assigned to Rejected
遠藤です。

解決済みなので close します。

-- 
Yusuke Endoh <mame@tsg.ne.jp>

Also available in: Atom PDF