diff --git a/activesupport/lib/active_support/core_ext/date/calculations.rb b/activesupport/lib/active_support/core_ext/date/calculations.rb index c60e833441..86d7fa1abf 100644 --- a/activesupport/lib/active_support/core_ext/date/calculations.rb +++ b/activesupport/lib/active_support/core_ext/date/calculations.rb @@ -1,12 +1,13 @@ require 'date' -require 'active_support/duration' require 'active_support/core_ext/object/acts_like' require 'active_support/core_ext/date/zones' +require 'active_support/core_ext/date/operators' require 'active_support/core_ext/time/zones' require 'active_support/core_ext/date_and_time/calculations' class Date include DateAndTime::Calculations + prepend ActiveSupport::DateOperators class << self attr_accessor :beginning_of_week_default @@ -85,26 +86,6 @@ class Date end alias :at_end_of_day :end_of_day - def plus_with_duration(other) #:nodoc: - if ActiveSupport::Duration === other - other.since(self) - else - plus_without_duration(other) - end - end - alias_method :plus_without_duration, :+ - alias_method :+, :plus_with_duration - - def minus_with_duration(other) #:nodoc: - if ActiveSupport::Duration === other - plus_with_duration(-other) - else - minus_without_duration(other) - end - end - alias_method :minus_without_duration, :- - alias_method :-, :minus_with_duration - # Provides precise Date calculations for years, months, and days. The +options+ parameter takes a hash with # any of these keys: :years, :months, :weeks, :days. def advance(options) @@ -129,15 +110,4 @@ class Date options.fetch(:day, day) ) end - - # Allow Date to be compared with Time by converting to DateTime and relying on the <=> from there. - def compare_with_coercion(other) - if other.is_a?(Time) - self.to_datetime <=> other - else - compare_without_coercion(other) - end - end - alias_method :compare_without_coercion, :<=> - alias_method :<=>, :compare_with_coercion end diff --git a/activesupport/lib/active_support/core_ext/date/operators.rb b/activesupport/lib/active_support/core_ext/date/operators.rb new file mode 100644 index 0000000000..decf099624 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/date/operators.rb @@ -0,0 +1,16 @@ +require 'active_support/core_ext/date_and_time/with_duration' + +module ActiveSupport + module DateOperators # :nodoc: + include DateAndTime::WithDuration + + # Allow Date to be compared with Time by converting to DateTime and relying on the <=> from there. + def <=>(other) + if other.is_a?(Time) + self.to_datetime <=> other + else + super + end + end + end +end diff --git a/activesupport/lib/active_support/core_ext/date_and_time/with_duration.rb b/activesupport/lib/active_support/core_ext/date_and_time/with_duration.rb new file mode 100644 index 0000000000..4a6c4013d5 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/date_and_time/with_duration.rb @@ -0,0 +1,23 @@ +require 'active_support/duration' + +module ActiveSupport + module DateAndTime + module WithDuration #:nodoc: + def +(other) #:nodoc: + if ActiveSupport::Duration === other + other.since(self) + else + super + end + end + + def -(other) #:nodoc: + if ActiveSupport::Duration === other + self + (-other) + else + super + end + end + end + end +end diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb index 1ce68ea7c7..dd99dd667a 100644 --- a/activesupport/lib/active_support/core_ext/time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/time/calculations.rb @@ -1,11 +1,12 @@ -require 'active_support/duration' require 'active_support/core_ext/time/conversions' require 'active_support/time_with_zone' require 'active_support/core_ext/time/zones' +require 'active_support/core_ext/time/operators' require 'active_support/core_ext/date_and_time/calculations' class Time include DateAndTime::Calculations + prepend ActiveSupport::TimeOperators COMMON_YEAR_DAYS_IN_MONTH = [nil, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] @@ -212,60 +213,4 @@ class Time def all_day beginning_of_day..end_of_day end - - def plus_with_duration(other) #:nodoc: - if ActiveSupport::Duration === other - other.since(self) - else - plus_without_duration(other) - end - end - alias_method :plus_without_duration, :+ - alias_method :+, :plus_with_duration - - def minus_with_duration(other) #:nodoc: - if ActiveSupport::Duration === other - other.until(self) - else - minus_without_duration(other) - end - end - alias_method :minus_without_duration, :- - alias_method :-, :minus_with_duration - - # Time#- can also be used to determine the number of seconds between two Time instances. - # We're layering on additional behavior so that ActiveSupport::TimeWithZone instances - # are coerced into values that Time#- will recognize - def minus_with_coercion(other) - other = other.comparable_time if other.respond_to?(:comparable_time) - other.is_a?(DateTime) ? to_f - other.to_f : minus_without_coercion(other) - end - alias_method :minus_without_coercion, :- - alias_method :-, :minus_with_coercion - - # Layers additional behavior on Time#<=> so that DateTime and ActiveSupport::TimeWithZone instances - # can be chronologically compared with a Time - def compare_with_coercion(other) - # we're avoiding Time#to_datetime and Time#to_time because they're expensive - if other.class == Time - compare_without_coercion(other) - elsif other.is_a?(Time) - compare_without_coercion(other.to_time) - else - to_datetime <=> other - end - end - alias_method :compare_without_coercion, :<=> - alias_method :<=>, :compare_with_coercion - - # Layers additional behavior on Time#eql? so that ActiveSupport::TimeWithZone instances - # can be eql? to an equivalent Time - def eql_with_coercion(other) - # if other is an ActiveSupport::TimeWithZone, coerce a Time instance from it so we can do eql? comparison - other = other.comparable_time if other.respond_to?(:comparable_time) - eql_without_coercion(other) - end - alias_method :eql_without_coercion, :eql? - alias_method :eql?, :eql_with_coercion - end diff --git a/activesupport/lib/active_support/core_ext/time/operators.rb b/activesupport/lib/active_support/core_ext/time/operators.rb new file mode 100644 index 0000000000..161304dcb3 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/time/operators.rb @@ -0,0 +1,36 @@ +require 'active_support/core_ext/date_and_time/with_duration' + +module ActiveSupport + module TimeOperators # :nodoc: + include DateAndTime::WithDuration + + # Layers additional behavior on Time#<=> so that DateTime and ActiveSupport::TimeWithZone instances + # can be chronologically compared with a Time + def <=>(other) + # we're avoiding Time#to_datetime and Time#to_time because they're expensive + if other.class == Time + super + elsif other.is_a?(Time) + super(other.to_time) + else + to_datetime <=> other + end + end + + # Layers additional behavior on Time#eql? so that ActiveSupport::TimeWithZone instances + # can be eql? to an equivalent Time + def eql?(other) + # if other is an ActiveSupport::TimeWithZone, coerce a Time instance from it so we can do eql? comparison + other = other.comparable_time if other.respond_to?(:comparable_time) + super + end + + # Time#- can also be used to determine the number of seconds between two Time instances. + # We're layering on additional behavior so that ActiveSupport::TimeWithZone instances + # are coerced into values that Time#- will recognize + def -(other) + other = other.comparable_time if other.respond_to?(:comparable_time) + other.is_a?(DateTime) ? to_f - other.to_f : super + end + end +end