提交 ac03ad1f 编写于 作者: G Geoff Buesing

Adding Time and DateTime #compare_with_coercion, which layers behavior on #<=>...

Adding Time and DateTime #compare_with_coercion, which layers behavior on #<=> so that any combination of Time, DateTime and ActiveSupport::TimeWithZone instances can be chronologically compared

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@8711 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
上级 213fac6f
*SVN*
* Adding Time and DateTime #compare_with_coercion, which layers behavior on #<=> so that any combination of Time, DateTime and ActiveSupport::TimeWithZone instances can be chronologically compared [Geoff Buesing]
* TimeZone#now returns an ActiveSupport::TimeWithZone [Geoff Buesing]
* Time #in_current_time_zone and #change_time_zone_to_current return self when Time.zone is nil [Geoff Buesing]
......
......@@ -7,6 +7,11 @@ module DateTime #:nodoc:
module Calculations
def self.included(base) #:nodoc:
base.extend ClassMethods
base.class_eval do
alias_method :compare_without_coercion, :<=>
alias_method :<=>, :compare_with_coercion
end
end
module ClassMethods
......@@ -91,6 +96,13 @@ def utc?
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 compare_with_coercion(other)
other = other.comparable_time if other.respond_to?(:comparable_time)
other = other.to_datetime unless other.acts_like?(:date)
compare_without_coercion(other)
end
end
end
end
......
......@@ -9,8 +9,12 @@ def self.included(base) #:nodoc:
base.class_eval do
alias_method :plus_without_duration, :+
alias_method :+, :plus_with_duration
alias_method :minus_without_duration, :-
alias_method :-, :minus_with_duration
alias_method :compare_without_coercion, :<=>
alias_method :<=>, :compare_with_coercion
end
end
......@@ -218,6 +222,19 @@ def minus_with_duration(other) #:nodoc:
minus_without_duration(other)
end
end
# Layers additional behavior on Time#<=> so that DateTime and ActiveSupport::TimeWithZone instances
# can be chronologically compared with a Time
def compare_with_coercion(other)
# if other is an ActiveSupport::TimeWithZone, coerce a Time instance from it so we can do <=> comparision
other = other.comparable_time if other.respond_to?(:comparable_time)
if other.acts_like?(:date)
# other is a Date/DateTime, so coerce self #to_datetime and hand off to DateTime#<=>
to_datetime.compare_without_coercion(other)
else
compare_without_coercion(other)
end
end
end
end
end
......
......@@ -105,7 +105,6 @@ def strftime(format)
# Use the time in UTC for comparisons
def <=>(other)
other = other.comparable_time if other.respond_to?(:comparable_time) # to coerce time from TimeWithZone
utc <=> other
end
......
......@@ -253,6 +253,24 @@ def test_formatted_offset_with_local
assert_equal '-05:00', dt.formatted_offset
assert_equal '-0500', dt.formatted_offset(false)
end
def test_compare_with_time
assert_equal 1, DateTime.civil(2000) <=> Time.utc(1999, 12, 31, 23, 59, 59)
assert_equal 0, DateTime.civil(2000) <=> Time.utc(2000, 1, 1, 0, 0, 0)
assert_equal(-1, DateTime.civil(2000) <=> Time.utc(2000, 1, 1, 0, 0, 1))
end
def test_compare_with_datetime
assert_equal 1, DateTime.civil(2000) <=> DateTime.civil(1999, 12, 31, 23, 59, 59)
assert_equal 0, DateTime.civil(2000) <=> DateTime.civil(2000, 1, 1, 0, 0, 0)
assert_equal(-1, DateTime.civil(2000) <=> DateTime.civil(2000, 1, 1, 0, 0, 1))
end
def test_compare_with_time_with_zone
assert_equal 1, DateTime.civil(2000) <=> ActiveSupport::TimeWithZone.new( Time.utc(1999, 12, 31, 23, 59, 59) )
assert_equal 0, DateTime.civil(2000) <=> ActiveSupport::TimeWithZone.new( Time.utc(2000, 1, 1, 0, 0, 0) )
assert_equal(-1, DateTime.civil(2000) <=> ActiveSupport::TimeWithZone.new( Time.utc(2000, 1, 1, 0, 0, 1) ))
end
protected
def with_timezone(new_tz = 'US/Eastern')
......
......@@ -424,6 +424,24 @@ def test_formatted_offset_with_local
assert_equal '-0400', Time.local(2000, 7).formatted_offset(false)
end
end
def test_compare_with_time
assert_equal 1, Time.utc(2000) <=> Time.utc(1999, 12, 31, 23, 59, 59, 999)
assert_equal 0, Time.utc(2000) <=> Time.utc(2000, 1, 1, 0, 0, 0)
assert_equal(-1, Time.utc(2000) <=> Time.utc(2000, 1, 1, 0, 0, 0, 001))
end
def test_compare_with_datetime
assert_equal 1, Time.utc(2000) <=> DateTime.civil(1999, 12, 31, 23, 59, 59)
assert_equal 0, Time.utc(2000) <=> DateTime.civil(2000, 1, 1, 0, 0, 0)
assert_equal(-1, Time.utc(2000) <=> DateTime.civil(2000, 1, 1, 0, 0, 1))
end
def test_compare_with_time_with_zone
assert_equal 1, Time.utc(2000) <=> ActiveSupport::TimeWithZone.new( Time.utc(1999, 12, 31, 23, 59, 59) )
assert_equal 0, Time.utc(2000) <=> ActiveSupport::TimeWithZone.new( Time.utc(2000, 1, 1, 0, 0, 0) )
assert_equal(-1, Time.utc(2000) <=> ActiveSupport::TimeWithZone.new( Time.utc(2000, 1, 1, 0, 0, 1) ))
end
protected
def with_timezone(new_tz = 'US/Eastern')
......
......@@ -87,12 +87,24 @@ def test_to_s_db
def test_xmlschema
assert_equal "1999-12-31T19:00:00-05:00", @twz.xmlschema
end
def test_compare
def test_compare_with_time
assert_equal 1, @twz <=> Time.utc(1999, 12, 31, 23, 59, 59)
assert_equal 0, @twz <=> Time.utc(2000)
assert_equal 0, @twz <=> Time.utc(2000, 1, 1, 0, 0, 0)
assert_equal(-1, @twz <=> Time.utc(2000, 1, 1, 0, 0, 1))
end
def test_compare_with_datetime
assert_equal 1, @twz <=> DateTime.civil(1999, 12, 31, 23, 59, 59)
assert_equal 0, @twz <=> DateTime.civil(2000, 1, 1, 0, 0, 0)
assert_equal(-1, @twz <=> DateTime.civil(2000, 1, 1, 0, 0, 1))
end
def test_compare_with_time_with_zone
assert_equal 1, @twz <=> ActiveSupport::TimeWithZone.new( Time.utc(1999, 12, 31, 23, 59, 59) )
assert_equal 0, @twz <=> ActiveSupport::TimeWithZone.new( Time.utc(2000, 1, 1, 0, 0, 0) )
assert_equal(-1, @twz <=> ActiveSupport::TimeWithZone.new( Time.utc(2000, 1, 1, 0, 0, 1) ))
end
def test_plus
assert_equal Time.utc(1999, 12, 31, 19, 0 ,5), (@twz + 5).time
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册