mirror of https://github.com/rails/rails
fix: equivalent negative durations add to the same time (#43795)
* bug: illustrate negative durations don't add to the same time * fix: equivalent negative durations add to the same time Co-authored-by: Caleb <me@cpb.ca> Co-authored-by: Braden Staudacher <braden.staudacher@chime.com> * Updates CHANGELOG with fix to `ActiveSupport::Duration.build`
This commit is contained in:
parent
1410c3fd1d
commit
ffc1e5f889
|
@ -1,3 +1,10 @@
|
|||
* Fix `ActiveSupport::Duration.build` to support negative values.
|
||||
|
||||
The algorithm to collect the `parts` of the `ActiveSupport::Duration`
|
||||
ignored the sign of the `value` and accumulated incorrect part values. This
|
||||
impacted `ActiveSupport::Duration#sum` (which is dependent on `parts`) but
|
||||
not `ActiveSupport::Duration#eql?` (which is dependent on `value`).
|
||||
|
||||
*Caleb Buxton*, *Braden Staudacher*
|
||||
|
||||
Please check [7-0-stable](https://github.com/rails/rails/blob/7-0-stable/activesupport/CHANGELOG.md) for previous changes.
|
||||
|
|
|
@ -191,13 +191,14 @@ module ActiveSupport
|
|||
end
|
||||
|
||||
parts = {}
|
||||
remainder = value.round(9)
|
||||
remainder_sign = value <=> 0
|
||||
remainder = value.round(9).abs
|
||||
variable = false
|
||||
|
||||
PARTS.each do |part|
|
||||
unless part == :seconds
|
||||
part_in_seconds = PARTS_IN_SECONDS[part]
|
||||
parts[part] = remainder.div(part_in_seconds)
|
||||
parts[part] = remainder.div(part_in_seconds) * remainder_sign
|
||||
remainder %= part_in_seconds
|
||||
|
||||
unless parts[part].zero?
|
||||
|
@ -206,7 +207,7 @@ module ActiveSupport
|
|||
end
|
||||
end unless value == 0
|
||||
|
||||
parts[:seconds] = remainder
|
||||
parts[:seconds] = remainder * remainder_sign
|
||||
|
||||
new(value, parts, variable)
|
||||
end
|
||||
|
|
|
@ -752,6 +752,17 @@ class DurationTest < ActiveSupport::TestCase
|
|||
assert (1.day + 12.hours).variable?
|
||||
end
|
||||
|
||||
def test_duration_symmetry
|
||||
time = Time.parse("Dec 7, 2021")
|
||||
expected_time = Time.parse("2021-12-06 23:59:59")
|
||||
|
||||
assert_equal expected_time, time + -1.second
|
||||
assert_equal expected_time, time + ActiveSupport::Duration.build(1) * -1
|
||||
assert_equal expected_time, time + -ActiveSupport::Duration.build(1)
|
||||
assert_equal expected_time, time + ActiveSupport::Duration::Scalar.new(-1)
|
||||
assert_equal expected_time, time + ActiveSupport::Duration.build(-1)
|
||||
end
|
||||
|
||||
private
|
||||
def eastern_time_zone
|
||||
if Gem.win_platform?
|
||||
|
|
Loading…
Reference in New Issue