diff options
-rw-r--r-- | ext/date/date_core.c | 41 | ||||
-rw-r--r-- | test/date/test_date_arith.rb | 14 |
2 files changed, 36 insertions, 19 deletions
diff --git a/ext/date/date_core.c b/ext/date/date_core.c index e214a65f46..5fc5053f88 100644 --- a/ext/date/date_core.c +++ b/ext/date/date_core.c @@ -2333,6 +2333,9 @@ VALUE date_zone_to_diff(VALUE); static int offset_to_sec(VALUE vof, int *rof) { + int try_rational = 1; + + again: switch (TYPE(vof)) { case T_FIXNUM: { @@ -2359,10 +2362,11 @@ offset_to_sec(VALUE vof, int *rof) default: expect_numeric(vof); vof = f_to_r(vof); -#ifdef CANONICALIZATION_FOR_MATHN - if (!k_rational_p(vof)) - return offset_to_sec(vof, rof); -#endif + if (!k_rational_p(vof)) { + if (!try_rational) Check_Type(vof, T_RATIONAL); + try_rational = 0; + goto again; + } /* fall through */ case T_RATIONAL: { @@ -2371,17 +2375,10 @@ offset_to_sec(VALUE vof, int *rof) vs = day_to_sec(vof); -#ifdef CANONICALIZATION_FOR_MATHN if (!k_rational_p(vs)) { - if (!FIXNUM_P(vs)) - return 0; - n = FIX2LONG(vs); - if (n < -DAY_IN_SECONDS || n > DAY_IN_SECONDS) - return 0; - *rof = (int)n; - return 1; + vn = vs; + goto rounded; } -#endif vn = rb_rational_num(vs); vd = rb_rational_den(vs); @@ -2391,6 +2388,7 @@ offset_to_sec(VALUE vof, int *rof) vn = f_round(vs); if (!f_eqeq_p(vn, vs)) rb_warning("fraction of offset is ignored"); + rounded: if (!FIXNUM_P(vn)) return 0; n = FIX2LONG(vn); @@ -5513,8 +5511,10 @@ d_lite_new_offset(int argc, VALUE *argv, VALUE self) static VALUE d_lite_plus(VALUE self, VALUE other) { + int try_rational = 1; get_d1(self); + again: switch (TYPE(other)) { case T_FIXNUM: { @@ -5724,18 +5724,21 @@ d_lite_plus(VALUE self, VALUE other) default: expect_numeric(other); other = f_to_r(other); -#ifdef CANONICALIZATION_FOR_MATHN - if (!k_rational_p(other)) - return d_lite_plus(self, other); -#endif + if (!k_rational_p(other)) { + if (!try_rational) Check_Type(other, T_RATIONAL); + try_rational = 0; + goto again; + } /* fall through */ case T_RATIONAL: { VALUE nth, sf, t; int jd, df, s; - if (wholenum_p(other)) - return d_lite_plus(self, rb_rational_num(other)); + if (wholenum_p(other)) { + other = rb_rational_num(other); + goto again; + } if (f_positive_p(other)) s = +1; diff --git a/test/date/test_date_arith.rb b/test/date/test_date_arith.rb index 94822e5764..e1f29dbf22 100644 --- a/test/date/test_date_arith.rb +++ b/test/date/test_date_arith.rb @@ -3,11 +3,18 @@ require 'test/unit' require 'date' class TestDateArith < Test::Unit::TestCase + class Rat < Numeric + def to_r; self; end + end def test_new_offset d = DateTime.new(2002, 3, 14) assert_equal(Rational(9, 24), d.new_offset(Rational(9, 24)).offset) assert_equal(Rational(9, 24), d.new_offset('+0900').offset) + n = Rat.new + assert_raise(TypeError) do + Timeout.timeout(1) {d.new_offset(n)} + end end def test__plus @@ -37,6 +44,13 @@ class TestDateArith < Test::Unit::TestCase assert_raise(e) do DateTime.new(2000,2,29) + Time.mktime(2000,2,29) end + n = Rat.new + assert_raise(e) do + Timeout.timeout(1) {Date.new(2000,2,29) + n} + end + assert_raise(e) do + Timeout.timeout(1) {DateTime.new(2000,2,29) + n} + end end def test__minus |