aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activesupport/CHANGELOG.md13
-rw-r--r--activesupport/lib/active_support/core_ext/date.rb1
-rw-r--r--activesupport/lib/active_support/core_ext/date/infinite_comparable.rb5
-rw-r--r--activesupport/lib/active_support/core_ext/date_time.rb1
-rw-r--r--activesupport/lib/active_support/core_ext/date_time/calculations.rb7
-rw-r--r--activesupport/lib/active_support/core_ext/date_time/infinite_comparable.rb5
-rw-r--r--activesupport/lib/active_support/core_ext/infinite_comparable.rb30
-rw-r--r--activesupport/lib/active_support/core_ext/numeric.rb1
-rw-r--r--activesupport/lib/active_support/core_ext/numeric/infinite_comparable.rb11
-rw-r--r--activesupport/lib/active_support/core_ext/time.rb1
-rw-r--r--activesupport/lib/active_support/core_ext/time/infinite_comparable.rb5
-rw-r--r--activesupport/test/core_ext/date_ext_test.rb7
-rw-r--r--activesupport/test/core_ext/date_time_ext_test.rb9
-rw-r--r--activesupport/test/core_ext/numeric_ext_test.rb64
-rw-r--r--activesupport/test/core_ext/range_ext_test.rb25
-rw-r--r--activesupport/test/core_ext/time_ext_test.rb9
-rw-r--r--activesupport/test/core_ext/time_with_zone_test.rb12
17 files changed, 199 insertions, 7 deletions
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index 6917be7efc..bee93ebfbc 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -1,5 +1,18 @@
## Rails 4.0.0 (unreleased) ##
+* It's now possible to compare Date, DateTime, Time and TimeWithZone with Infinity
+ This allows to create date/time ranges with one infinite bound.
+ Example:
+
+ range = Range.new(Date.today, Float::INFINITY)
+
+ Also it's possible to check inclusion of date/time in range with conversion.
+
+ range.include?(Time.now + 1.year) # => true
+ range.include?(DateTime.now + 1.year) # => true
+
+ *Alexander Grebennik*
+
* Remove meaningless `ActiveSupport::FrozenObjectError`, which was just an alias of `RuntimeError`.
*Akira Matsuda*
diff --git a/activesupport/lib/active_support/core_ext/date.rb b/activesupport/lib/active_support/core_ext/date.rb
index 465fedda80..5f13f5f70f 100644
--- a/activesupport/lib/active_support/core_ext/date.rb
+++ b/activesupport/lib/active_support/core_ext/date.rb
@@ -2,4 +2,5 @@ require 'active_support/core_ext/date/acts_like'
require 'active_support/core_ext/date/calculations'
require 'active_support/core_ext/date/conversions'
require 'active_support/core_ext/date/zones'
+require 'active_support/core_ext/date/infinite_comparable'
diff --git a/activesupport/lib/active_support/core_ext/date/infinite_comparable.rb b/activesupport/lib/active_support/core_ext/date/infinite_comparable.rb
new file mode 100644
index 0000000000..ca5d793942
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/date/infinite_comparable.rb
@@ -0,0 +1,5 @@
+require 'active_support/core_ext/infinite_comparable'
+
+class Date
+ include InfiniteComparable
+end
diff --git a/activesupport/lib/active_support/core_ext/date_time.rb b/activesupport/lib/active_support/core_ext/date_time.rb
index e8a27b9f38..024af91738 100644
--- a/activesupport/lib/active_support/core_ext/date_time.rb
+++ b/activesupport/lib/active_support/core_ext/date_time.rb
@@ -2,3 +2,4 @@ require 'active_support/core_ext/date_time/acts_like'
require 'active_support/core_ext/date_time/calculations'
require 'active_support/core_ext/date_time/conversions'
require 'active_support/core_ext/date_time/zones'
+require 'active_support/core_ext/date_time/infinite_comparable'
diff --git a/activesupport/lib/active_support/core_ext/date_time/calculations.rb b/activesupport/lib/active_support/core_ext/date_time/calculations.rb
index fca5d4d679..4e4852a5e6 100644
--- a/activesupport/lib/active_support/core_ext/date_time/calculations.rb
+++ b/activesupport/lib/active_support/core_ext/date_time/calculations.rb
@@ -142,11 +142,4 @@ class DateTime
def utc_offset
(offset * 86400).to_i
end
-
- # Layers additional behavior on DateTime#<=> so that Time and
- # ActiveSupport::TimeWithZone instances can be compared with a DateTime.
- def <=>(other)
- super other.to_datetime
- end
-
end
diff --git a/activesupport/lib/active_support/core_ext/date_time/infinite_comparable.rb b/activesupport/lib/active_support/core_ext/date_time/infinite_comparable.rb
new file mode 100644
index 0000000000..8a282b19f2
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/date_time/infinite_comparable.rb
@@ -0,0 +1,5 @@
+require 'active_support/core_ext/infinite_comparable'
+
+class DateTime
+ include InfiniteComparable
+end
diff --git a/activesupport/lib/active_support/core_ext/infinite_comparable.rb b/activesupport/lib/active_support/core_ext/infinite_comparable.rb
new file mode 100644
index 0000000000..a69ff6a37b
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/infinite_comparable.rb
@@ -0,0 +1,30 @@
+require 'active_support/concern'
+
+module InfiniteComparable
+ extend ActiveSupport::Concern
+
+ included do
+ alias_method_chain :<=>, :infinity
+ end
+
+ define_method '<=>_with_infinity' do |other|
+ if other.class == self.class
+ self.send(:'<=>_without_infinity', other)
+ # inf <=> inf
+ elsif other.respond_to?(:infinite?) && other.infinite? && respond_to?(:infinite?) && infinite?
+ infinite? <=> other.infinite?
+ # not_inf <=> inf
+ elsif other.respond_to?(:infinite?) && other.infinite?
+ -other.infinite?
+ # inf <=> not_inf
+ elsif respond_to?(:infinite?) && infinite?
+ infinite?
+ else
+ conversion = :"to_#{self.class.name.downcase}"
+
+ other = other.send(conversion) if other.respond_to?(conversion)
+
+ self.send(:'<=>_without_infinity', other)
+ end
+ end
+end
diff --git a/activesupport/lib/active_support/core_ext/numeric.rb b/activesupport/lib/active_support/core_ext/numeric.rb
index a6bc0624be..d5cfc2ece4 100644
--- a/activesupport/lib/active_support/core_ext/numeric.rb
+++ b/activesupport/lib/active_support/core_ext/numeric.rb
@@ -1,3 +1,4 @@
require 'active_support/core_ext/numeric/bytes'
require 'active_support/core_ext/numeric/time'
require 'active_support/core_ext/numeric/conversions'
+require 'active_support/core_ext/numeric/infinite_comparable'
diff --git a/activesupport/lib/active_support/core_ext/numeric/infinite_comparable.rb b/activesupport/lib/active_support/core_ext/numeric/infinite_comparable.rb
new file mode 100644
index 0000000000..07d4d7446a
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/numeric/infinite_comparable.rb
@@ -0,0 +1,11 @@
+require 'active_support/core_ext/big_decimal/conversions'
+require 'active_support/number_helper'
+require 'active_support/core_ext/infinite_comparable'
+
+class Float
+ include InfiniteComparable
+end
+
+class BigDecimal
+ include InfiniteComparable
+end
diff --git a/activesupport/lib/active_support/core_ext/time.rb b/activesupport/lib/active_support/core_ext/time.rb
index 32cffe237d..af6b589b71 100644
--- a/activesupport/lib/active_support/core_ext/time.rb
+++ b/activesupport/lib/active_support/core_ext/time.rb
@@ -3,3 +3,4 @@ require 'active_support/core_ext/time/calculations'
require 'active_support/core_ext/time/conversions'
require 'active_support/core_ext/time/marshal'
require 'active_support/core_ext/time/zones'
+require 'active_support/core_ext/time/infinite_comparable'
diff --git a/activesupport/lib/active_support/core_ext/time/infinite_comparable.rb b/activesupport/lib/active_support/core_ext/time/infinite_comparable.rb
new file mode 100644
index 0000000000..63795885f5
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/time/infinite_comparable.rb
@@ -0,0 +1,5 @@
+require 'active_support/core_ext/infinite_comparable'
+
+class Time
+ include InfiniteComparable
+end
diff --git a/activesupport/test/core_ext/date_ext_test.rb b/activesupport/test/core_ext/date_ext_test.rb
index 5e89a6e00b..f8b219fee6 100644
--- a/activesupport/test/core_ext/date_ext_test.rb
+++ b/activesupport/test/core_ext/date_ext_test.rb
@@ -353,6 +353,13 @@ class DateExtBehaviorTest < ActiveSupport::TestCase
Date.today.freeze.freeze
end
end
+
+ def test_compare_with_infinity
+ assert_nothing_raised do
+ assert_equal(-1, Date.today <=> Float::INFINITY)
+ assert_equal(1, Date.today <=> -Float::INFINITY)
+ end
+ end
end
class DateExtConversionsTest < ActiveSupport::TestCase
diff --git a/activesupport/test/core_ext/date_time_ext_test.rb b/activesupport/test/core_ext/date_time_ext_test.rb
index dfad3a90f8..1bcec7aac4 100644
--- a/activesupport/test/core_ext/date_time_ext_test.rb
+++ b/activesupport/test/core_ext/date_time_ext_test.rb
@@ -317,3 +317,12 @@ class DateTimeExtCalculationsTest < ActiveSupport::TestCase
old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ')
end
end
+
+class DateTimeExtBehaviorTest < ActiveSupport::TestCase
+ def test_compare_with_infinity
+ assert_nothing_raised do
+ assert_equal(-1, DateTime.now <=> Float::INFINITY)
+ assert_equal(1, DateTime.now <=> -Float::INFINITY)
+ end
+ end
+end
diff --git a/activesupport/test/core_ext/numeric_ext_test.rb b/activesupport/test/core_ext/numeric_ext_test.rb
index 435f4aa5a1..5839aa40e5 100644
--- a/activesupport/test/core_ext/numeric_ext_test.rb
+++ b/activesupport/test/core_ext/numeric_ext_test.rb
@@ -447,3 +447,67 @@ class NumericExtFormattingTest < ActiveSupport::TestCase
assert_equal '1 Million', BigDecimal("1000010").to_s(:human)
end
end
+
+class NumericExtBehaviorTest < ActiveSupport::TestCase
+ def setup
+ @inf = BigDecimal.new('Infinity')
+ end
+
+ def test_compare_infinity_with_date
+ assert_nothing_raised do
+ assert_equal(-1, -Float::INFINITY <=> Date.today)
+ assert_equal(1, Float::INFINITY <=> Date.today)
+ assert_equal(-1, -@inf <=> Date.today)
+ assert_equal(1, @inf <=> Date.today)
+ end
+ end
+
+ def test_compare_infinty_with_infinty
+ assert_nothing_raised do
+ assert_equal(-1, -Float::INFINITY <=> Float::INFINITY)
+ assert_equal(1, Float::INFINITY <=> -Float::INFINITY)
+ assert_equal(0, Float::INFINITY <=> Float::INFINITY)
+ assert_equal(0, -Float::INFINITY <=> -Float::INFINITY)
+
+ assert_equal(-1, -Float::INFINITY <=> BigDecimal::INFINITY)
+ assert_equal(1, Float::INFINITY <=> -BigDecimal::INFINITY)
+ assert_equal(0, Float::INFINITY <=> BigDecimal::INFINITY)
+ assert_equal(0, -Float::INFINITY <=> -BigDecimal::INFINITY)
+
+ assert_equal(-1, -BigDecimal::INFINITY <=> Float::INFINITY)
+ assert_equal(1, BigDecimal::INFINITY <=> -Float::INFINITY)
+ assert_equal(0, BigDecimal::INFINITY <=> Float::INFINITY)
+ assert_equal(0, -BigDecimal::INFINITY <=> -Float::INFINITY)
+ end
+ end
+
+ def test_compare_infinity_with_time
+ assert_nothing_raised do
+ assert_equal(-1, -Float::INFINITY <=> Time.now)
+ assert_equal(1, Float::INFINITY <=> Time.now)
+ assert_equal(-1, -@inf <=> Time.now)
+ assert_equal(1, @inf <=> Time.now)
+ end
+ end
+
+ def test_compare_infinity_with_datetime
+ assert_nothing_raised do
+ assert_equal(-1, -Float::INFINITY <=> DateTime.now)
+ assert_equal(1, Float::INFINITY <=> DateTime.now)
+ assert_equal(-1, -@inf <=> DateTime.now)
+ assert_equal(1, @inf <=> DateTime.now)
+ end
+ end
+
+ def test_compare_infinity_with_twz
+ time_zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
+ twz = ActiveSupport::TimeWithZone.new(Time.now, time_zone)
+
+ assert_nothing_raised do
+ assert_equal(-1, -Float::INFINITY <=> twz)
+ assert_equal(1, Float::INFINITY <=> twz)
+ assert_equal(-1, -@inf <=> twz)
+ assert_equal(1, @inf <=> twz)
+ end
+ end
+end
diff --git a/activesupport/test/core_ext/range_ext_test.rb b/activesupport/test/core_ext/range_ext_test.rb
index f0cdc0bfd4..0051c48984 100644
--- a/activesupport/test/core_ext/range_ext_test.rb
+++ b/activesupport/test/core_ext/range_ext_test.rb
@@ -1,6 +1,7 @@
require 'abstract_unit'
require 'active_support/time'
require 'active_support/core_ext/range'
+require 'active_support/core_ext/numeric'
class RangeTest < ActiveSupport::TestCase
def test_to_s_from_dates
@@ -85,4 +86,28 @@ class RangeTest < ActiveSupport::TestCase
time_range_2 = Time.utc(2005, 12, 10, 17, 31)..Time.utc(2005, 12, 10, 18, 00)
assert !time_range_1.overlaps?(time_range_2)
end
+
+ def test_infinite_bounds
+ time_zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
+
+ time = Time.now
+ date = Date.today
+ datetime = DateTime.now
+ twz = ActiveSupport::TimeWithZone.new(time, time_zone)
+
+ infinity1 = Float::INFINITY
+ infinity2 = BigDecimal.new('Infinity')
+
+ [infinity1, infinity2].each do |infinity|
+ [time, date, datetime, twz].each do |bound|
+ [time, date, datetime, twz].each do |value|
+ assert Range.new(bound, infinity).include?(value + 10.years)
+ assert Range.new(-infinity, bound).include?(value - 10.years)
+
+ assert !Range.new(bound, infinity).include?(value - 10.years)
+ assert !Range.new(-infinity, bound).include?(value + 10.years)
+ end
+ end
+ end
+ end
end
diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb
index 70e07cefd1..1c75530084 100644
--- a/activesupport/test/core_ext/time_ext_test.rb
+++ b/activesupport/test/core_ext/time_ext_test.rb
@@ -843,3 +843,12 @@ class TimeExtMarshalingTest < ActiveSupport::TestCase
assert_equal Time.local(2004, 2, 29), Time.local(2004, 5, 31).last_quarter
end
end
+
+class TimeExtBehaviorTest < ActiveSupport::TestCase
+ def test_compare_with_infinity
+ assert_nothing_raised do
+ assert_equal(-1, Time.now <=> Float::INFINITY)
+ assert_equal(1, Time.now <=> -Float::INFINITY)
+ end
+ end
+end
diff --git a/activesupport/test/core_ext/time_with_zone_test.rb b/activesupport/test/core_ext/time_with_zone_test.rb
index 56020da035..76dc6a35c8 100644
--- a/activesupport/test/core_ext/time_with_zone_test.rb
+++ b/activesupport/test/core_ext/time_with_zone_test.rb
@@ -1081,3 +1081,15 @@ class TimeWithZoneMethodsForString < ActiveSupport::TestCase
Time.zone = old_tz
end
end
+
+class TimeWithZoneExtBehaviorTest < ActiveSupport::TestCase
+ def test_compare_with_infinity
+ time_zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
+ twz = ActiveSupport::TimeWithZone.new(Time.now, time_zone)
+
+ assert_nothing_raised do
+ assert_equal(-1, twz <=> Float::INFINITY)
+ assert_equal(1, twz <=> -Float::INFINITY)
+ end
+ end
+end