Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Backports Date#>> from 1.9 so that calculations do the right thing ar…

…ound the calendar reform

Our next_month gives November for some late dates in September of 1582.
Related methods, last_*, and in general advance have the same issues.
This commit fixes those, see the test suite for expected behavior, which
we still run in 1.9 to ensure it matches as we do with other methods
defined in Date in 1.9.
  • Loading branch information...
commit 636ffa1f089a51c98fce616191846eaba93d7b87 1 parent 605c645
@fxn fxn authored
View
2  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]
View
18 activesupport/lib/active_support/core_ext/date/calculations.rb
@@ -4,6 +4,24 @@
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
View
27 activesupport/test/core_ext/date_ext_test.rb
@@ -145,6 +145,10 @@ def test_last_year_in_leap_years
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 @@ def test_next_year_in_leap_years
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 @@ def test_advance
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)
Please sign in to comment.
Something went wrong with that request. Please try again.