diff options
author | Andrey Novikov <envek@envek.name> | 2017-01-09 01:43:49 +0300 |
---|---|---|
committer | Andrey Novikov <envek@envek.name> | 2017-01-09 23:04:48 +0300 |
commit | cb9d0e4864fa68fad9c49b880c32e90ddf0545bd (patch) | |
tree | 4e6b00404b69cb0d9b08ad3c413c5c27027a5dba /activesupport/test | |
parent | 3bc747bd8676dc940b531067e2861dcd4ac28efc (diff) | |
download | rails-cb9d0e4864fa68fad9c49b880c32e90ddf0545bd.tar.gz rails-cb9d0e4864fa68fad9c49b880c32e90ddf0545bd.tar.bz2 rails-cb9d0e4864fa68fad9c49b880c32e90ddf0545bd.zip |
Fix inconsistent results when parsing large durations and constructing durations from code
ActiveSupport::Duration.parse('P3Y') == 3.years # It should be true
Duration parsing made independent from any moment of time:
Fixed length in seconds is assigned to each duration part during parsing.
Changed duration of months and years in seconds to more accurate and logical:
1. The value of 365.2425 days in Gregorian year is more accurate
as it accounts for every 400th non-leap year.
2. Month's length is bound to year's duration, which makes
sensible comparisons like `12.months == 1.year` to be `true`
and nonsensical ones like `30.days == 1.month` to be `false`.
Calculations on times and dates with durations shouldn't be affected as
duration's numeric value isn't used in calculations, only parts are used.
Methods on `Numeric` like `2.days` now use these predefined durations
to avoid duplicating of duration constants through the codebase and
eliminate creation of intermediate durations.
Diffstat (limited to 'activesupport/test')
-rw-r--r-- | activesupport/test/core_ext/duration_test.rb | 1 | ||||
-rw-r--r-- | activesupport/test/core_ext/numeric_ext_test.rb | 10 |
2 files changed, 6 insertions, 5 deletions
diff --git a/activesupport/test/core_ext/duration_test.rb b/activesupport/test/core_ext/duration_test.rb index fc0dd41d0e..8c4c08ffd4 100644 --- a/activesupport/test/core_ext/duration_test.rb +++ b/activesupport/test/core_ext/duration_test.rb @@ -340,6 +340,7 @@ class DurationTest < ActiveSupport::TestCase travel_to Time.utc(2016, 11, 4) do assert_equal 604800, ActiveSupport::Duration.parse("P7D").to_i assert_equal 604800, ActiveSupport::Duration.parse("P1W").to_i + assert_equal ActiveSupport::Duration.parse(3.years.iso8601).to_i, 3.years.to_i end end end diff --git a/activesupport/test/core_ext/numeric_ext_test.rb b/activesupport/test/core_ext/numeric_ext_test.rb index 5361b7b708..5f86bf97c8 100644 --- a/activesupport/test/core_ext/numeric_ext_test.rb +++ b/activesupport/test/core_ext/numeric_ext_test.rb @@ -12,7 +12,7 @@ class NumericExtTimeAndDateTimeTest < ActiveSupport::TestCase 10.minutes => 600, 1.hour + 15.minutes => 4500, 2.days + 4.hours + 30.minutes => 189000, - 5.years + 1.month + 1.fortnight => 161589600 + 5.years + 1.month + 1.fortnight => 161624106 } end @@ -61,10 +61,10 @@ class NumericExtTimeAndDateTimeTest < ActiveSupport::TestCase end def test_duration_after_conversion_is_no_longer_accurate - assert_equal 30.days.to_i.seconds.since(@now), 1.month.to_i.seconds.since(@now) - assert_equal 365.25.days.to_f.seconds.since(@now), 1.year.to_f.seconds.since(@now) - assert_equal 30.days.to_i.seconds.since(@dtnow), 1.month.to_i.seconds.since(@dtnow) - assert_equal 365.25.days.to_f.seconds.since(@dtnow), 1.year.to_f.seconds.since(@dtnow) + assert_equal (1.year / 12).to_i.seconds.since(@now), 1.month.to_i.seconds.since(@now) + assert_equal 365.2425.days.to_f.seconds.since(@now), 1.year.to_f.seconds.since(@now) + assert_equal (1.year / 12).to_i.seconds.since(@dtnow), 1.month.to_i.seconds.since(@dtnow) + assert_equal 365.2425.days.to_f.seconds.since(@dtnow), 1.year.to_f.seconds.since(@dtnow) end def test_add_one_year_to_leap_day |