ふなばです。

ダテクラスを書いていて、あらためて気がついた lib/date.rb の疑問点です。

`-' で period が <= 0 にならないようにチェックしていますが、`-' で必要な
らば、`+' でも必要なはずだと思います (増加するばかりとは限らない)。

ダテクラスのテストのついでに、lib/date.rb のテストもしてみました。
lib/date.rb は暦計算を間違えることがあります。1601年1月1日から2000年12月
31日まで (146097日) 日付の対応を確認したところ、そのうちの7867日で誤りが
みつかりました。

require 'date'
x = Date.new(1752, 12, 31)
x += 1
puts x # => "Fri, Jan  1 1753"
x -= 1
puts x # => "Mon, Jan 11 1753"

これは `-' がよくないわけではなくて、暦計算そのものがよくないわけです。

で、あまり自信がないのですが、ちょろっと手を入れてみました。一応、これ
でうまくいっているようです。でも、本当に確かなのか、わかりませんから、
信用しないでください。

--- date.rb.orig	Wed Feb 18 11:31:19 1998
+++ date.rb	Mon Mar  2 19:11:47 1998
@@ -109,6 +109,9 @@
     else
       raise TypeError, "Illegal type. (Integer or Date)"
     end
+    if d <= 0
+      raise ArgumentError, "argument out of range. (self > other)"
+    end
     return Date.at(d)
   end
   
@@ -146,11 +149,7 @@
   end
   
   def leapyear?
-    if Date.leapyear(@year) == 1
-      return FALSE
-    else
-      return TRUE
-    end
+    Date.leapyear(@year) != 1
   end
 
   def _check_date
@@ -221,10 +220,10 @@
     p += dl[mm]
   end
   p += (y - 1) * 365 + ((y - 1) / 4.0).to_i
-  if (y - 1) > 1752
-    p -= ((y - 1 - 1752) / 100.0).to_i
-    p += ((y - 1 - 1752) / 400.0).to_i
-    p -= (14 - 3)
+  if y > 1752
+    p -= ((y - 1) / 100.0).to_i
+    p += ((y - 1) / 400.0).to_i
+    p += 2
   elsif y == 1752 && m == 9 && d >= 14 && d <= 30
     p -= (14 - 3)
   end

#ついでですが、マニュアルの Time#gm で month の記述が修正されていないよう
#です。

--Tadayoshi Funaba