Skip to content
This repository
Browse code

Fix Time#advance bug when trying to advance a year from leap day. Clo…

…ses #8655 [gbuesing]

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@7262 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information...
commit 4b6411008675dbbfb7da4dfb6ef73c5528c196d1 1 parent bbbc451
risk danger olson technoweenie authored
2  activesupport/CHANGELOG
... ... @@ -1,5 +1,7 @@
1 1 *SVN*
2 2
  3 +* Fix Time#advance bug when trying to advance a year from leap day. Closes #8655 [gbuesing]
  4 +
3 5 * Add support for []= on ActiveSupport::Multibyte::Chars. Closes #9142. [ewan, manfred]
4 6
5 7 * Added Array#extract_options! to encapsulate the pattern of getting an options hash out of a variable number of parameters #8759 [norbert].
9 activesupport/lib/active_support/core_ext/date/calculations.rb
@@ -68,9 +68,10 @@ def minus_with_duration(other) #:nodoc:
68 68 # Provides precise Date calculations for years, months, and days. The +options+ parameter takes a hash with
69 69 # any of these keys: :months, :days, :years.
70 70 def advance(options)
71   - d = ::Date.new(year + (options.delete(:years) || 0), month, day)
72   - d = d >> options.delete(:months) if options[:months]
73   - d = d + options.delete(:days) if options[:days]
  71 + d = self
  72 + d = d >> options.delete(:years) * 12 if options[:years]
  73 + d = d >> options.delete(:months) if options[:months]
  74 + d = d + options.delete(:days) if options[:days]
74 75 d
75 76 end
76 77
@@ -78,7 +79,7 @@ def advance(options)
78 79 #
79 80 # Examples:
80 81 #
81   - # Date.new(2007, 5, 12).change(:day => 1) # => Date.new(2007, 5, 12)
  82 + # Date.new(2007, 5, 12).change(:day => 1) # => Date.new(2007, 5, 1)
82 83 # Date.new(2007, 5, 12).change(:year => 2005, :month => 1) # => Date.new(2005, 1, 12)
83 84 def change(options)
84 85 ::Date.new(
4 activesupport/lib/active_support/core_ext/date_time/calculations.rb
@@ -30,9 +30,7 @@ def change(options)
30 30 # Uses Date to provide precise Time calculations for years, months, and days. The +options+ parameter takes a hash with
31 31 # any of these keys: :months, :days, :years.
32 32 def advance(options)
33   - d = ::Date.new(year + (options.delete(:years) || 0), month, day)
34   - d = d >> options.delete(:months) if options[:months]
35   - d = d + options.delete(:days) if options[:days]
  33 + d = to_date.advance(options)
36 34 change(options.merge(:year => d.year, :month => d.month, :day => d.day))
37 35 end
38 36
6 activesupport/lib/active_support/core_ext/time/calculations.rb
@@ -72,10 +72,8 @@ def change(options)
72 72 # Uses Date to provide precise Time calculations for years, months, and days. The +options+ parameter takes a hash with
73 73 # any of these keys: :months, :days, :years.
74 74 def advance(options)
75   - d = ::Date.new(year + (options.delete(:years) || 0), month, day)
76   - d = d >> options.delete(:months) if options[:months]
77   - d = d + options.delete(:days) if options[:days]
78   - change(options.merge(:year => d.year, :month => d.month, :mday => d.day))
  75 + d = to_date.advance(options)
  76 + change(options.merge(:year => d.year, :month => d.month, :day => d.day))
79 77 end
80 78
81 79 # Returns a new Time representing the time a number of seconds ago, this is basically a wrapper around the Numeric extension
1  activesupport/test/core_ext/date_ext_test.rb
@@ -121,6 +121,7 @@ def test_plus
121 121 assert_equal Date.new(2005,6,28), Date.new(2005,2,28).advance(:months => 4)
122 122 assert_equal Date.new(2012,9,28), Date.new(2005,2,28).advance(:years => 7, :months => 7)
123 123 assert_equal Date.new(2013,10,3), Date.new(2005,2,28).advance(:years => 7, :months => 19, :days => 5)
  124 + assert_equal Date.new(2005,2,28), Date.new(2004,2,29).advance(:years => 1) #leap day plus one year
124 125 end
125 126
126 127 def test_next_week
1  activesupport/test/core_ext/date_time_ext_test.rb
@@ -163,6 +163,7 @@ def test_plus
163 163 assert_equal DateTime.civil(2005,6,28,15,15,10), DateTime.civil(2005,2,28,15,15,10).advance(:months => 4)
164 164 assert_equal DateTime.civil(2012,9,28,15,15,10), DateTime.civil(2005,2,28,15,15,10).advance(:years => 7, :months => 7)
165 165 assert_equal DateTime.civil(2013,10,3,15,15,10), DateTime.civil(2005,2,28,15,15,10).advance(:years => 7, :months => 19, :days => 5)
  166 + assert_equal DateTime.civil(2005,2,28,15,15,10), DateTime.civil(2004,2,29,15,15,10).advance(:years => 1) #leap day plus one year
166 167 end
167 168
168 169 def test_next_week
9 activesupport/test/core_ext/numeric_ext_test.rb
@@ -80,6 +80,11 @@ def test_duration_after_convertion_is_no_longer_accurate
80 80 assert_equal 30.days.to_i.since(@dtnow), 1.month.to_i.since(@dtnow)
81 81 assert_equal 365.25.days.to_f.since(@dtnow), 1.year.to_f.since(@dtnow)
82 82 end
  83 +
  84 + def test_add_one_year_to_leap_day
  85 + assert_equal Time.utc(2005,2,28,15,15,10), Time.utc(2004,2,29,15,15,10) + 1.year
  86 + assert_equal DateTime.civil(2005,2,28,15,15,10), DateTime.civil(2004,2,29,15,15,10) + 1.year
  87 + end
83 88 end
84 89
85 90 class NumericExtDateTest < Test::Unit::TestCase
@@ -99,6 +104,10 @@ def test_chaining_duration_operations
99 104 assert_equal @today.advance(:days => 2).advance(:months => -3), @today + 2.days - 3.months
100 105 assert_equal @today.advance(:days => 1).advance(:months => 2), @today + 1.day + 2.months
101 106 end
  107 +
  108 + def test_add_one_year_to_leap_day
  109 + assert_equal Date.new(2005,2,28), Date.new(2004,2,29) + 1.year
  110 + end
102 111 end
103 112
104 113 class NumericExtSizeTest < Test::Unit::TestCase
2  activesupport/test/core_ext/time_ext_test.rb
@@ -238,6 +238,7 @@ def test_plus
238 238 assert_equal Time.local(2005,6,28,15,15,10), Time.local(2005,2,28,15,15,10).advance(:months => 4)
239 239 assert_equal Time.local(2012,9,28,15,15,10), Time.local(2005,2,28,15,15,10).advance(:years => 7, :months => 7)
240 240 assert_equal Time.local(2013,10,3,15,15,10), Time.local(2005,2,28,15,15,10).advance(:years => 7, :months => 19, :days => 5)
  241 + assert_equal Time.local(2005,2,28,15,15,10), Time.local(2004,2,29,15,15,10).advance(:years => 1) #leap day plus one year
241 242 end
242 243
243 244 def test_utc_plus
@@ -245,6 +246,7 @@ def test_utc_plus
245 246 assert_equal Time.utc(2005,6,22,15,15,10), Time.utc(2005,2,22,15,15,10).advance(:months => 4)
246 247 assert_equal Time.utc(2012,9,22,15,15,10), Time.utc(2005,2,22,15,15,10).advance(:years => 7, :months => 7)
247 248 assert_equal Time.utc(2013,10,3,15,15,10), Time.utc(2005,2,22,15,15,10).advance(:years => 7, :months => 19, :days => 11)
  249 + assert_equal Time.utc(2005,2,28,15,15,10), Time.utc(2004,2,29,15,15,10).advance(:years => 1) #leap day plus one year
248 250 end
249 251
250 252 def test_next_week

0 comments on commit 4b64110

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