Skip to content
Browse files

Maintain proleptic gregorian in Time#advance

Time#advance uses Time#to_date and Date#advance to calculate a new date.
The Date object returned by Time#to_date is constructed with the assumption
that the Time object represents a proleptic gregorian date, but it is
configured to observe the default julian calendar reform date (2299161j)
for purposes of calculating month, date and year:

  Time.new(1582, 10, 4).to_date.to_s           # => "1582-09-24"
  Time.new(1582, 10, 4).to_date.gregorian.to_s # => "1582-10-04"

This patch ensures that when the intermediate Date object is advanced
to yield a new Date object, that the Time object for return is contructed
with a proleptic gregorian month, date and year.
  • Loading branch information...
1 parent e2f3e50 commit 0c6ddbe7b0056cb5c17d6b483c0e5a7cbd596b97 Riley Lynch committed May 15, 2013
View
10 activesupport/lib/active_support/core_ext/time/calculations.rb
@@ -110,10 +110,11 @@ def change(options)
end
end
- # Uses Date to provide precise Time calculations for years, months, and days.
- # The +options+ parameter takes a hash with any of these keys: <tt>:years</tt>,
- # <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>, <tt>:hours</tt>,
- # <tt>:minutes</tt>, <tt>:seconds</tt>.
+ # Uses Date to provide precise Time calculations for years, months, and days
+ # according to the proleptic Gregorian calendar. The +options+ parameter
+ # takes a hash with any of these keys: <tt>:years</tt>, <tt>:months</tt>,
+ # <tt>:weeks</tt>, <tt>:days</tt>, <tt>:hours</tt>, <tt>:minutes</tt>,
+ # <tt>:seconds</tt>.
def advance(options)
unless options[:weeks].nil?
options[:weeks], partial_weeks = options[:weeks].divmod(1)
@@ -126,6 +127,7 @@ def advance(options)
end
d = to_date.advance(options)
+ d = d.gregorian if d.julian?
time_advanced_by_date = change(:year => d.year, :month => d.month, :day => d.day)
seconds_to_advance = \
options.fetch(:seconds, 0) +
View
7 activesupport/test/core_ext/time_ext_test.rb
@@ -464,6 +464,13 @@ def test_advance_with_nsec
assert_equal t, t.advance(:months => 0)
end
+ def test_advance_gregorian_proleptic
+ assert_equal Time.local(1582,10,14,15,15,10), Time.local(1582,10,15,15,15,10).advance(:days => -1)
+ assert_equal Time.local(1582,10,15,15,15,10), Time.local(1582,10,14,15,15,10).advance(:days => 1)
+ assert_equal Time.local(1582,10,5,15,15,10), Time.local(1582,10,4,15,15,10).advance(:days => 1)
+ assert_equal Time.local(1582,10,4,15,15,10), Time.local(1582,10,5,15,15,10).advance(:days => -1)
+ end
+
def test_last_week
with_env_tz 'US/Eastern' do
assert_equal Time.local(2005,2,21), Time.local(2005,3,1,15,15,10).last_week

0 comments on commit 0c6ddbe

Please sign in to comment.
Something went wrong with that request. Please try again.