aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activesupport/lib/active_support/duration.rb12
-rw-r--r--activesupport/test/core_ext/duration_test.rb11
2 files changed, 20 insertions, 3 deletions
diff --git a/activesupport/lib/active_support/duration.rb b/activesupport/lib/active_support/duration.rb
index 82322291d0..ad2e139ea6 100644
--- a/activesupport/lib/active_support/duration.rb
+++ b/activesupport/lib/active_support/duration.rb
@@ -15,16 +15,22 @@ module ActiveSupport
autoload :ISO8601Serializer, "active_support/duration/iso8601_serializer"
def initialize(value, parts) #:nodoc:
- @value, @parts = value, parts
+ @value, @parts = value, parts.to_h
+ @parts.default = 0
end
# Adds another Duration or a Numeric to this Duration. Numeric values
# are treated as seconds.
def +(other)
if Duration === other
- Duration.new(value + other.value, @parts + other.parts)
+ parts = @parts.dup
+ other.parts.each do |(key, value)|
+ parts[key] += value
+ end
+ Duration.new(value + other.value, parts)
else
- Duration.new(value + other, @parts + [[:seconds, other]])
+ seconds = @parts[:seconds] + other
+ Duration.new(value + other, @parts.merge(seconds: seconds))
end
end
diff --git a/activesupport/test/core_ext/duration_test.rb b/activesupport/test/core_ext/duration_test.rb
index b7b4a9dd00..26a9ea4aee 100644
--- a/activesupport/test/core_ext/duration_test.rb
+++ b/activesupport/test/core_ext/duration_test.rb
@@ -345,6 +345,17 @@ class DurationTest < ActiveSupport::TestCase
end
end
+ def test_adding_durations_do_not_hold_prior_states
+ time = Time.parse("Nov 29, 2016")
+ # If the implementation adds and subtracts 3 months, the
+ # resulting date would have been in February so the day will
+ # change to the 29th.
+ d1 = 3.months - 3.months
+ d2 = 2.months - 2.months
+
+ assert_equal time + d1, time + d2
+ end
+
private
def eastern_time_zone
if Gem.win_platform?