提交 32f215c3 编写于 作者: S Sean Griffin

Treat combined durations as a single unit

Prior to this commit, `3.months - 3.months` would result in a duration
that has the "parts" of `[[:months, 3], [:months, -3]]`. This would mean
that it was subtly different than `2.months - 2.months`. When applied to
a time, the date might actually change if the resulting day doesn't
exist however many months in the future, even though in both cases we
just wanted to add `0`, which should always be an identity operation.

With this change, we now store the parts as a hash, so `3.months -
3.months` is simply stored as `{ months: 0 }`.
上级 4806317b
...@@ -15,16 +15,22 @@ class Duration ...@@ -15,16 +15,22 @@ class Duration
autoload :ISO8601Serializer, "active_support/duration/iso8601_serializer" autoload :ISO8601Serializer, "active_support/duration/iso8601_serializer"
def initialize(value, parts) #:nodoc: def initialize(value, parts) #:nodoc:
@value, @parts = value, parts @value, @parts = value, parts.to_h
@parts.default = 0
end end
# Adds another Duration or a Numeric to this Duration. Numeric values # Adds another Duration or a Numeric to this Duration. Numeric values
# are treated as seconds. # are treated as seconds.
def +(other) def +(other)
if Duration === 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 else
Duration.new(value + other, @parts + [[:seconds, other]]) seconds = @parts[:seconds] + other
Duration.new(value + other, @parts.merge(seconds: seconds))
end end
end end
......
...@@ -345,6 +345,17 @@ def test_iso8601_parsing_across_autumn_dst_boundary ...@@ -345,6 +345,17 @@ def test_iso8601_parsing_across_autumn_dst_boundary
end end
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 private
def eastern_time_zone def eastern_time_zone
if Gem.win_platform? if Gem.win_platform?
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册