diff options
-rw-r--r-- | activesupport/CHANGELOG | 2 | ||||
-rw-r--r-- | activesupport/lib/active_support/core_ext/date/calculations.rb | 18 | ||||
-rw-r--r-- | activesupport/test/core_ext/date_ext_test.rb | 27 |
3 files changed, 47 insertions, 0 deletions
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG index 3061bcef4f..1e01cfc45f 100644 --- a/activesupport/CHANGELOG +++ b/activesupport/CHANGELOG @@ -1,5 +1,7 @@ *Rails 3.0.0 [beta 4/release candidate] (unreleased)* +* Backports Date#>> from 1.9 so that calculations do the right thing around the calendar reform. [fxn] + * Date#to_time handles properly years in the range 0..138. [fxn] * Deprecate {{}} as interpolation syntax for I18n in favor of %{} [José Valim] diff --git a/activesupport/lib/active_support/core_ext/date/calculations.rb b/activesupport/lib/active_support/core_ext/date/calculations.rb index fef49e1003..2612dca93a 100644 --- a/activesupport/lib/active_support/core_ext/date/calculations.rb +++ b/activesupport/lib/active_support/core_ext/date/calculations.rb @@ -4,6 +4,24 @@ require 'active_support/core_ext/time/zones' require 'active_support/core_ext/object/acts_like' class Date + if RUBY_VERSION < '1.9' + undef :>> + + # Backported from 1.9. The one in 1.8 leads to incorrect next_month and + # friends for dates where the calendar reform is involved. It additionally + # prevents an infinite loop fixed in r27013. + def >>(n) + y, m = (year * 12 + (mon - 1) + n).divmod(12) + m, = (m + 1) .divmod(1) + d = mday + until jd2 = self.class.valid_civil?(y, m, d, start) + d -= 1 + raise ArgumentError, 'invalid date' unless d > 0 + end + self + (jd2 - jd) + end + end + class << self # Returns a new Date representing the date 1 day ago (i.e. yesterday's date). def yesterday diff --git a/activesupport/test/core_ext/date_ext_test.rb b/activesupport/test/core_ext/date_ext_test.rb index d5f3eed8c1..e70fc729ce 100644 --- a/activesupport/test/core_ext/date_ext_test.rb +++ b/activesupport/test/core_ext/date_ext_test.rb @@ -145,6 +145,10 @@ class DateExtCalculationsTest < Test::Unit::TestCase assert_equal Date.new(1999,2,28), Date.new(2000,2,29).last_year end + def test_last_year_in_calendar_reform + assert_equal Date.new(1582,10,4), Date.new(1583,10,14).last_year + end + def test_next_year assert_equal Date.new(2006,6,5), Date.new(2005,6,5).next_year end @@ -153,16 +157,28 @@ class DateExtCalculationsTest < Test::Unit::TestCase assert_equal Date.new(2001,2,28), Date.new(2000,2,29).next_year end + def test_next_year_in_calendar_reform + assert_equal Date.new(1582,10,4), Date.new(1581,10,10).next_year + end + def test_yesterday assert_equal Date.new(2005,2,21), Date.new(2005,2,22).yesterday assert_equal Date.new(2005,2,28), Date.new(2005,3,2).yesterday.yesterday end + def test_yesterday_in_calendar_reform + assert_equal Date.new(1582,10,4), Date.new(1582,10,15).yesterday + end + def test_tomorrow assert_equal Date.new(2005,2,23), Date.new(2005,2,22).tomorrow assert_equal Date.new(2005,3,2), Date.new(2005,2,28).tomorrow.tomorrow end + def test_tomorrow_in_calendar_reform + assert_equal Date.new(1582,10,15), Date.new(1582,10,4).tomorrow + end + def test_advance assert_equal Date.new(2006,2,28), Date.new(2005,2,28).advance(:years => 1) assert_equal Date.new(2005,6,28), Date.new(2005,2,28).advance(:months => 4) @@ -174,6 +190,17 @@ class DateExtCalculationsTest < Test::Unit::TestCase assert_equal Date.new(2005,2,28), Date.new(2004,2,29).advance(:years => 1) #leap day plus one year end + def test_advance_calendar_reform + assert_equal Date.new(1582,10,15), Date.new(1582,10,4).advance(:days => 1) + assert_equal Date.new(1582,10,4), Date.new(1582,10,15).advance(:days => -1) + 5.upto(14) do |day| + assert_equal Date.new(1582,10,4), Date.new(1582,9,day).advance(:months => 1) + assert_equal Date.new(1582,10,4), Date.new(1582,11,day).advance(:months => -1) + assert_equal Date.new(1582,10,4), Date.new(1581,10,day).advance(:years => 1) + assert_equal Date.new(1582,10,4), Date.new(1583,10,day).advance(:years => -1) + end + end + def test_next_week assert_equal Date.new(2005,2,28), Date.new(2005,2,22).next_week assert_equal Date.new(2005,3,4), Date.new(2005,2,22).next_week(:friday) |