You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
3.9 KiB
103 lines
3.9 KiB
From 28938dd64c8b4fa1943d0b878d3d832b94fa12a3 Mon Sep 17 00:00:00 2001
|
|
From: Andrew White <andrew.white@unboxed.co>
|
|
Date: Sat, 20 May 2017 16:33:09 +0100
|
|
Subject: [PATCH] Fix implicit calculations with scalars and durations
|
|
|
|
Previously calculations where the scalar is first would be converted
|
|
to a duration of seconds but this causes issues with dates being
|
|
converted to times, e.g:
|
|
|
|
Time.zone = "Beijing" # => Asia/Shanghai
|
|
date = Date.civil(2017, 5, 20) # => Mon, 20 May 2017
|
|
2 * 1.day # => 172800 seconds
|
|
date + 2 * 1.day # => Mon, 22 May 2017 00:00:00 CST +08:00
|
|
|
|
Now the `ActiveSupport::Duration::Scalar` calculation methods will try
|
|
to maintain the part structure of the duration where possible, e.g:
|
|
|
|
Time.zone = "Beijing" # => Asia/Shanghai
|
|
date = Date.civil(2017, 5, 20) # => Mon, 20 May 2017
|
|
2 * 1.day # => 2 days
|
|
date + 2 * 1.day # => Mon, 22 May 2017
|
|
|
|
Fixes #29160, #28970.
|
|
---
|
|
activesupport/CHANGELOG.md | 22 +++++++++++++++
|
|
activesupport/lib/active_support/duration.rb | 41 ++++++++++++++++++++++++----
|
|
activesupport/test/core_ext/duration_test.rb | 34 +++++++++++++++++++++++
|
|
3 files changed, 91 insertions(+), 6 deletions(-)
|
|
|
|
diff --git a/activesupport/test/core_ext/duration_test.rb b/activesupport/test/core_ext/duration_test.rb
|
|
index 1648a9b27060..3108f24f218c 100644
|
|
--- a/activesupport/test/core_ext/duration_test.rb
|
|
+++ b/activesupport/test/core_ext/duration_test.rb
|
|
@@ -337,6 +337,13 @@ def test_scalar_plus
|
|
assert_equal "no implicit conversion of String into ActiveSupport::Duration::Scalar", exception.message
|
|
end
|
|
|
|
+ def test_scalar_plus_parts
|
|
+ scalar = ActiveSupport::Duration::Scalar.new(10)
|
|
+
|
|
+ assert_equal({ days: 1, seconds: 10 }, (scalar + 1.day).parts)
|
|
+ assert_equal({ days: -1, seconds: 10 }, (scalar + -1.day).parts)
|
|
+ end
|
|
+
|
|
def test_scalar_minus
|
|
scalar = ActiveSupport::Duration::Scalar.new(10)
|
|
|
|
@@ -349,6 +356,9 @@ def test_scalar_minus
|
|
assert_equal 5, scalar - 5.seconds
|
|
assert_instance_of ActiveSupport::Duration, scalar - 5.seconds
|
|
|
|
+ assert_equal({ days: -1, seconds: 10 }, (scalar - 1.day).parts)
|
|
+ assert_equal({ days: 1, seconds: 10 }, (scalar - -1.day).parts)
|
|
+
|
|
exception = assert_raises(TypeError) do
|
|
scalar - "foo"
|
|
end
|
|
@@ -356,6 +366,13 @@ def test_scalar_minus
|
|
assert_equal "no implicit conversion of String into ActiveSupport::Duration::Scalar", exception.message
|
|
end
|
|
|
|
+ def test_scalar_minus_parts
|
|
+ scalar = ActiveSupport::Duration::Scalar.new(10)
|
|
+
|
|
+ assert_equal({ days: -1, seconds: 10 }, (scalar - 1.day).parts)
|
|
+ assert_equal({ days: 1, seconds: 10 }, (scalar - -1.day).parts)
|
|
+ end
|
|
+
|
|
def test_scalar_multiply
|
|
scalar = ActiveSupport::Duration::Scalar.new(5)
|
|
|
|
@@ -375,6 +392,14 @@ def test_scalar_multiply
|
|
assert_equal "no implicit conversion of String into ActiveSupport::Duration::Scalar", exception.message
|
|
end
|
|
|
|
+ def test_scalar_multiply_parts
|
|
+ scalar = ActiveSupport::Duration::Scalar.new(1)
|
|
+ assert_equal({ days: 2 }, (scalar * 2.days).parts)
|
|
+ assert_equal(172800, (scalar * 2.days).value)
|
|
+ assert_equal({ days: -2 }, (scalar * -2.days).parts)
|
|
+ assert_equal(-172800, (scalar * -2.days).value)
|
|
+ end
|
|
+
|
|
def test_scalar_divide
|
|
scalar = ActiveSupport::Duration::Scalar.new(10)
|
|
|
|
@@ -394,6 +419,15 @@ def test_scalar_divide
|
|
assert_equal "no implicit conversion of String into ActiveSupport::Duration::Scalar", exception.message
|
|
end
|
|
|
|
+ def test_scalar_divide_parts
|
|
+ scalar = ActiveSupport::Duration::Scalar.new(10)
|
|
+
|
|
+ assert_equal({ days: 2 }, (scalar / 5.days).parts)
|
|
+ assert_equal(172800, (scalar / 5.days).value)
|
|
+ assert_equal({ days: -2 }, (scalar / -5.days).parts)
|
|
+ assert_equal(-172800, (scalar / -5.days).value)
|
|
+ end
|
|
+
|
|
def test_twelve_months_equals_one_year
|
|
assert_equal 12.months, 1.year
|
|
end
|