X-Git-Url: https://git.njae.me.uk/?a=blobdiff_plain;f=vendor%2Frails%2Factivesupport%2Flib%2Factive_support%2Fduration.rb;fp=vendor%2Frails%2Factivesupport%2Flib%2Factive_support%2Fduration.rb;h=8eae85d38e9d1d22e5f2b246820c5ed47f837794;hb=d115f2e23823271635bad69229a42cd8ac68debe;hp=0000000000000000000000000000000000000000;hpb=37cb670bf3ddde90b214e591f100ed4446469484;p=depot.git diff --git a/vendor/rails/activesupport/lib/active_support/duration.rb b/vendor/rails/activesupport/lib/active_support/duration.rb new file mode 100644 index 0000000..8eae85d --- /dev/null +++ b/vendor/rails/activesupport/lib/active_support/duration.rb @@ -0,0 +1,96 @@ +module ActiveSupport + # Provides accurate date and time measurements using Date#advance and + # Time#advance, respectively. It mainly supports the methods on Numeric, + # such as in this example: + # + # 1.month.ago # equivalent to Time.now.advance(:months => -1) + class Duration < BasicObject + attr_accessor :value, :parts + + def initialize(value, parts) #:nodoc: + @value, @parts = value, parts + end + + # Adds another Duration or a Numeric to this Duration. Numeric values + # are treated as seconds. + def +(other) + if Duration === other + Duration.new(value + other.value, @parts + other.parts) + else + Duration.new(value + other, @parts + [[:seconds, other]]) + end + end + + # Subtracts another Duration or a Numeric from this Duration. Numeric + # values are treated as seconds. + def -(other) + self + (-other) + end + + def -@ #:nodoc: + Duration.new(-value, parts.map { |type,number| [type, -number] }) + end + + def is_a?(klass) #:nodoc: + klass == Duration || super + end + + # Returns true if other is also a Duration instance with the + # same value, or if other == value. + def ==(other) + if Duration === other + other.value == value + else + other == value + end + end + + def self.===(other) #:nodoc: + other.is_a?(Duration) rescue super + end + + # Calculates a new Time or Date that is as far in the future + # as this Duration represents. + def since(time = ::Time.current) + sum(1, time) + end + alias :from_now :since + + # Calculates a new Time or Date that is as far in the past + # as this Duration represents. + def ago(time = ::Time.current) + sum(-1, time) + end + alias :until :ago + + def inspect #:nodoc: + consolidated = parts.inject(::Hash.new(0)) { |h,part| h[part.first] += part.last; h } + [:years, :months, :days, :minutes, :seconds].map do |length| + n = consolidated[length] + "#{n} #{n == 1 ? length.to_s.singularize : length.to_s}" if n.nonzero? + end.compact.to_sentence + end + + protected + + def sum(sign, time = ::Time.current) #:nodoc: + parts.inject(time) do |t,(type,number)| + if t.acts_like?(:time) || t.acts_like?(:date) + if type == :seconds + t.since(sign * number) + else + t.advance(type => sign * number) + end + else + raise ::ArgumentError, "expected a time or date, got #{time.inspect}" + end + end + end + + private + + def method_missing(method, *args, &block) #:nodoc: + value.send(method, *args) + end + end +end