diff options
Diffstat (limited to 'activesupport/lib/active_support/duration.rb')
-rw-r--r-- | activesupport/lib/active_support/duration.rb | 33 |
1 files changed, 19 insertions, 14 deletions
diff --git a/activesupport/lib/active_support/duration.rb b/activesupport/lib/active_support/duration.rb index 6ec0c3a70a..c9e8c8fdc4 100644 --- a/activesupport/lib/active_support/duration.rb +++ b/activesupport/lib/active_support/duration.rb @@ -7,22 +7,30 @@ module ActiveSupport # # 1.month.ago # equivalent to Time.now.advance(months: -1) class Duration + EPOCH = ::Time.utc(2000) + attr_accessor :value, :parts autoload :ISO8601Parser, "active_support/duration/iso8601_parser" autoload :ISO8601Serializer, "active_support/duration/iso8601_serializer" def initialize(value, parts) #:nodoc: - @value, @parts = value, parts + @value, @parts = value, parts.to_h + @parts.default = 0 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) + parts = @parts.dup + other.parts.each do |(key, value)| + parts[key] += value + end + Duration.new(value + other.value, parts) else - Duration.new(value + other, @parts + [[:seconds, other]]) + seconds = @parts[:seconds] + other + Duration.new(value + other, @parts.merge(seconds: seconds)) end end @@ -33,7 +41,7 @@ module ActiveSupport end def -@ #:nodoc: - Duration.new(-value, parts.map { |type,number| [type, -number] }) + Duration.new(-value, parts.map { |type, number| [type, -number] }) end def is_a?(klass) #:nodoc: @@ -119,7 +127,7 @@ module ActiveSupport def inspect #:nodoc: parts. - reduce(::Hash.new(0)) { |h,(l,r)| h[l] += r; h }. + reduce(::Hash.new(0)) { |h, (l, r)| h[l] += r; h }. sort_by { |unit, _ | [:years, :months, :weeks, :days, :hours, :minutes, :seconds].index(unit) }. map { |unit, val| "#{val} #{val == 1 ? unit.to_s.chop : unit.to_s}" }. to_sentence(locale: ::I18n.default_locale) @@ -129,7 +137,7 @@ module ActiveSupport to_i end - def respond_to_missing?(method, include_private=false) #:nodoc: + def respond_to_missing?(method, include_private = false) #:nodoc: @value.respond_to?(method, include_private) end @@ -140,8 +148,7 @@ module ActiveSupport # If invalid string is provided, it will raise +ActiveSupport::Duration::ISO8601Parser::ParsingError+. def self.parse(iso8601duration) parts = ISO8601Parser.new(iso8601duration).parse! - time = ::Time.current - new(time.advance(parts) - time, parts) + new(EPOCH.advance(parts) - EPOCH, parts) end # Build ISO 8601 Duration string for this duration. @@ -152,10 +159,10 @@ module ActiveSupport delegate :<=>, to: :value - protected + private - def sum(sign, time = ::Time.current) #:nodoc: - parts.inject(time) do |t,(type,number)| + def sum(sign, time = ::Time.current) + parts.inject(time) do |t, (type, number)| if t.acts_like?(:time) || t.acts_like?(:date) if type == :seconds t.since(sign * number) @@ -172,9 +179,7 @@ module ActiveSupport end end - private - - def method_missing(method, *args, &block) #:nodoc: + def method_missing(method, *args, &block) value.send(method, *args, &block) end end |