parent
ff1d32aceb
commit
db99af5fbf
@ -1,102 +0,0 @@
|
|||||||
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
|
|
@ -1,126 +0,0 @@
|
|||||||
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/CHANGELOG.md b/activesupport/CHANGELOG.md
|
|
||||||
index c50c1902fe53..bae573cf37ac 100644
|
|
||||||
--- a/activesupport/CHANGELOG.md
|
|
||||||
+++ b/activesupport/CHANGELOG.md
|
|
||||||
@@ -1,3 +1,25 @@
|
|
||||||
+* Fix implicit coercion 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.
|
|
||||||
+
|
|
||||||
+ *Andrew White*
|
|
||||||
+
|
|
||||||
## Rails 5.1.0 (April 27, 2017) ##
|
|
||||||
|
|
||||||
* `ActiveSupport::EventedFileUpdateChecker` no longer listens to
|
|
||||||
diff --git a/activesupport/lib/active_support/duration.rb b/activesupport/lib/active_support/duration.rb
|
|
||||||
index d4424ed792a4..39deb2313f5a 100644
|
|
||||||
--- a/activesupport/lib/active_support/duration.rb
|
|
||||||
+++ b/activesupport/lib/active_support/duration.rb
|
|
||||||
@@ -37,27 +37,56 @@ def <=>(other)
|
|
||||||
end
|
|
||||||
|
|
||||||
def +(other)
|
|
||||||
- calculate(:+, other)
|
|
||||||
+ if Duration === other
|
|
||||||
+ seconds = value + other.parts[:seconds]
|
|
||||||
+ new_parts = other.parts.merge(seconds: seconds)
|
|
||||||
+ new_value = value + other.value
|
|
||||||
+
|
|
||||||
+ Duration.new(new_value, new_parts)
|
|
||||||
+ else
|
|
||||||
+ calculate(:+, other)
|
|
||||||
+ end
|
|
||||||
end
|
|
||||||
|
|
||||||
def -(other)
|
|
||||||
- calculate(:-, other)
|
|
||||||
+ if Duration === other
|
|
||||||
+ seconds = value - other.parts[:seconds]
|
|
||||||
+ new_parts = other.parts.map { |part, other_value| [part, -other_value] }.to_h
|
|
||||||
+ new_parts = new_parts.merge(seconds: seconds)
|
|
||||||
+ new_value = value - other.value
|
|
||||||
+
|
|
||||||
+ Duration.new(new_value, new_parts)
|
|
||||||
+ else
|
|
||||||
+ calculate(:-, other)
|
|
||||||
+ end
|
|
||||||
end
|
|
||||||
|
|
||||||
def *(other)
|
|
||||||
- calculate(:*, other)
|
|
||||||
+ if Duration === other
|
|
||||||
+ new_parts = other.parts.map { |part, other_value| [part, value * other_value] }.to_h
|
|
||||||
+ new_value = value * other.value
|
|
||||||
+
|
|
||||||
+ Duration.new(new_value, new_parts)
|
|
||||||
+ else
|
|
||||||
+ calculate(:*, other)
|
|
||||||
+ end
|
|
||||||
end
|
|
||||||
|
|
||||||
def /(other)
|
|
||||||
- calculate(:/, other)
|
|
||||||
+ if Duration === other
|
|
||||||
+ new_parts = other.parts.map { |part, other_value| [part, value / other_value] }.to_h
|
|
||||||
+ new_value = new_parts.inject(0) { |total, (part, value)| total + value * Duration::PARTS_IN_SECONDS[part] }
|
|
||||||
+
|
|
||||||
+ Duration.new(new_value, new_parts)
|
|
||||||
+ else
|
|
||||||
+ calculate(:/, other)
|
|
||||||
+ end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
def calculate(op, other)
|
|
||||||
if Scalar === other
|
|
||||||
Scalar.new(value.public_send(op, other.value))
|
|
||||||
- elsif Duration === other
|
|
||||||
- Duration.seconds(value).public_send(op, other)
|
|
||||||
elsif Numeric === other
|
|
||||||
Scalar.new(value.public_send(op, other))
|
|
||||||
else
|
|
@ -1,2 +1,2 @@
|
|||||||
SHA512 (activesupport-5.1.1.gem) = 3ed4596c827182d95f98194cad8c981bbb1567e9a7c4dca06b129e1604f7fa68a425b2b521bc41b758b45ddadf143eed19f3455a3f85a64fe0a7fb00f762a5d8
|
SHA512 (activesupport-5.1.2-tests.tgz) = bab66903338b3e2c84952c574a6cddab06ac69c4d0d5092e0d8e8f2657ea6699b90f3ee6ed0d1bc628b4cfeb80e5baf4d2bc5afe210eee9503471fa2ef9e41fa
|
||||||
SHA512 (activesupport-5.1.1-tests.tgz) = ffe188866a38d8195c735a729ea854d6619629e28ab471a5920aa45f8da4895c026b0e872918c74d10ade4e2abeea302c9ad85a63eb38a50d960d4433ee1dd5b
|
SHA512 (activesupport-5.1.2.gem) = 30ba768622f15a3f4bba3d6692621a561be8cc82b9757119e5d9856009a0e5ecad82a7e34d0c7f6c1cf01c537718319e98a767865a1ae3074bc649279c828d33
|
||||||
|
Loading…
Reference in new issue