diff --git a/activesupport/lib/active_support/duration.rb b/activesupport/lib/active_support/duration.rb index 8b6866c20059b8bbb14342d3c671c1ecabc26260..ba5b7beaefc4f7f8c8ffbc7565037e0ca5872ab9 100644 --- a/activesupport/lib/active_support/duration.rb +++ b/activesupport/lib/active_support/duration.rb @@ -182,15 +182,15 @@ def years(value) #:nodoc: # def build(value) parts = {} - remainder = value.to_f + remainder = value.round(9) PARTS.each do |part| unless part == :seconds part_in_seconds = PARTS_IN_SECONDS[part] parts[part] = remainder.div(part_in_seconds) - remainder = (remainder % part_in_seconds).round(9) + remainder %= part_in_seconds end - end + end unless value == 0 parts[:seconds] = remainder @@ -209,7 +209,7 @@ def calculate_total_seconds(parts) def initialize(value, parts) #:nodoc: @value, @parts = value, parts.to_h @parts.default = 0 - @parts.reject! { |k, v| v.zero? } + @parts.reject! { |k, v| v.zero? } unless value == 0 end def coerce(other) #:nodoc: diff --git a/activesupport/test/core_ext/duration_test.rb b/activesupport/test/core_ext/duration_test.rb index cb87a6d2e9d65872c1ed10f794eaef029674bb78..8ec4f1d29b95f546f615f8065ab9071b18a49662 100644 --- a/activesupport/test/core_ext/duration_test.rb +++ b/activesupport/test/core_ext/duration_test.rb @@ -62,6 +62,7 @@ def test_eql def test_inspect assert_equal "0 seconds", 0.seconds.inspect + assert_equal "0 days", 0.days.inspect assert_equal "1 month", 1.month.inspect assert_equal "1 month and 1 day", (1.month + 1.day).inspect assert_equal "6 months and -2 days", (6.months - 2.days).inspect @@ -155,20 +156,29 @@ def test_modulo assert_instance_of ActiveSupport::Duration, 13.months % 1.year end + def test_date_added_with_zero_days + assert_equal Date.civil(2017, 1, 1), Date.civil(2017, 1, 1) + 0.days + assert_instance_of Date, Date.civil(2017, 1, 1) + 0.days + end + def test_date_added_with_multiplied_duration assert_equal Date.civil(2017, 1, 3), Date.civil(2017, 1, 1) + 1.day * 2 + assert_instance_of Date, Date.civil(2017, 1, 1) + 1.day * 2 end def test_date_added_with_multiplied_duration_larger_than_one_month assert_equal Date.civil(2017, 2, 15), Date.civil(2017, 1, 1) + 1.day * 45 + assert_instance_of Date, Date.civil(2017, 1, 1) + 1.day * 45 end def test_date_added_with_divided_duration assert_equal Date.civil(2017, 1, 3), Date.civil(2017, 1, 1) + 4.days / 2 + assert_instance_of Date, Date.civil(2017, 1, 1) + 4.days / 2 end def test_date_added_with_divided_duration_larger_than_one_month assert_equal Date.civil(2017, 2, 15), Date.civil(2017, 1, 1) + 90.days / 2 + assert_instance_of Date, Date.civil(2017, 1, 1) + 90.days / 2 end def test_plus_with_time