Class: ActiveSupport::Duration

Inherits:
Object
  • Object
show all
Defined in:
lib/active_support/duration.rb,
lib/active_support/duration/iso8601_parser.rb,
lib/active_support/duration/iso8601_serializer.rb

Overview

Provides accurate date and time measurements using Date#advance and Time#advance, respectively. It mainly supports the methods on Numeric.

1.month.ago       # equivalent to Time.now.advance(months: -1)

Defined Under Namespace

Classes: ISO8601Parser, ISO8601Serializer

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(value, parts) ⇒ Duration

:nodoc:



15
16
17
# File 'lib/active_support/duration.rb', line 15

def initialize(value, parts) #:nodoc:
  @value, @parts = value, parts
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object (private)

:nodoc:



177
178
179
# File 'lib/active_support/duration.rb', line 177

def method_missing(method, *args, &block) #:nodoc:
  value.send(method, *args, &block)
end

Instance Attribute Details

#partsObject

Returns the value of attribute parts.



10
11
12
# File 'lib/active_support/duration.rb', line 10

def parts
  @parts
end

#valueObject

Returns the value of attribute value.



10
11
12
# File 'lib/active_support/duration.rb', line 10

def value
  @value
end

Class Method Details

.===(other) ⇒ Object

:nodoc:



100
101
102
103
104
# File 'lib/active_support/duration.rb', line 100

def self.===(other) #:nodoc:
  other.is_a?(Duration)
rescue ::NoMethodError
  false
end

.parse(iso8601duration) ⇒ Object

Creates a new Duration from string formatted according to ISO 8601 Duration.

See ISO 8601 for more information. This method allows negative parts to be present in pattern. If invalid string is provided, it will raise ActiveSupport::Duration::ISO8601Parser::ParsingError.



141
142
143
144
145
# File 'lib/active_support/duration.rb', line 141

def self.parse(iso8601duration)
  parts = ISO8601Parser.new(iso8601duration).parse!
  time  = ::Time.current
  new(time.advance(parts) - time, parts)
end

Instance Method Details

#+(other) ⇒ Object

Adds another Duration or a Numeric to this Duration. Numeric values are treated as seconds.



21
22
23
24
25
26
27
# File 'lib/active_support/duration.rb', line 21

def +(other)
  if Duration === other
    Duration.new(value + other.value, @parts + other.parts)
  else
    Duration.new(value + other, @parts + [[:seconds, other]])
  end
end

#-(other) ⇒ Object

Subtracts another Duration or a Numeric from this Duration. Numeric values are treated as seconds.



31
32
33
# File 'lib/active_support/duration.rb', line 31

def -(other)
  self + (-other)
end

#-@Object

:nodoc:



35
36
37
# File 'lib/active_support/duration.rb', line 35

def -@ #:nodoc:
  Duration.new(-value, parts.map { |type,number| [type, -number] })
end

#==(other) ⇒ Object

Returns true if other is also a Duration instance with the same value, or if other == value.



50
51
52
53
54
55
56
# File 'lib/active_support/duration.rb', line 50

def ==(other)
  if Duration === other
    other.value == value
  else
    other == value
  end
end

#ago(time = ::Time.current) ⇒ Object Also known as: until

Calculates a new Time or Date that is as far in the past as this Duration represents.



115
116
117
# File 'lib/active_support/duration.rb', line 115

def ago(time = ::Time.current)
  sum(-1, time)
end

#as_json(options = nil) ⇒ Object

:nodoc:



128
129
130
# File 'lib/active_support/duration.rb', line 128

def as_json(options = nil) #:nodoc:
  to_i
end

#eql?(other) ⇒ Boolean

Returns true if other is also a Duration instance, which has the same parts as this one.

Returns:

  • (Boolean)


92
93
94
# File 'lib/active_support/duration.rb', line 92

def eql?(other)
  Duration === other && other.value.eql?(value)
end

#hashObject



96
97
98
# File 'lib/active_support/duration.rb', line 96

def hash
  @value.hash
end

#inspectObject

:nodoc:



120
121
122
123
124
125
126
# File 'lib/active_support/duration.rb', line 120

def inspect #:nodoc:
  parts.
    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)
end

#instance_of?(klass) ⇒ Boolean

:nodoc:

Returns:

  • (Boolean)


44
45
46
# File 'lib/active_support/duration.rb', line 44

def instance_of?(klass) # :nodoc:
  Duration == klass || value.instance_of?(klass)
end

#is_a?(klass) ⇒ Boolean Also known as: kind_of?

:nodoc:

Returns:

  • (Boolean)


39
40
41
# File 'lib/active_support/duration.rb', line 39

def is_a?(klass) #:nodoc:
  Duration == klass || value.is_a?(klass)
end

#iso8601(precision: nil) ⇒ Object

Build ISO 8601 Duration string for this duration. The precision parameter can be used to limit seconds’ precision of duration.



149
150
151
# File 'lib/active_support/duration.rb', line 149

def iso8601(precision: nil)
  ISO8601Serializer.new(self, precision: precision).serialize
end

#respond_to_missing?(method, include_private = false) ⇒ Boolean

:nodoc:

Returns:

  • (Boolean)


132
133
134
# File 'lib/active_support/duration.rb', line 132

def respond_to_missing?(method, include_private=false) #:nodoc:
  @value.respond_to?(method, include_private)
end

#since(time = ::Time.current) ⇒ Object Also known as: from_now

Calculates a new Time or Date that is as far in the future as this Duration represents.



108
109
110
# File 'lib/active_support/duration.rb', line 108

def since(time = ::Time.current)
  sum(1, time)
end

#to_iObject

Returns the number of seconds that this Duration represents.

1.minute.to_i   # => 60
1.hour.to_i     # => 3600
1.day.to_i      # => 86400

Note that this conversion makes some assumptions about the duration of some periods, e.g. months are always 30 days and years are 365.25 days:

# equivalent to 30.days.to_i
1.month.to_i    # => 2592000

# equivalent to 365.25.days.to_i
1.year.to_i     # => 31557600

In such cases, Ruby’s core Date and Time should be used for precision date and time arithmetic.



86
87
88
# File 'lib/active_support/duration.rb', line 86

def to_i
  @value.to_i
end

#to_sObject

Returns the amount of seconds a duration covers as a string. For more information check to_i method.

1.day.to_s # => "86400"


62
63
64
# File 'lib/active_support/duration.rb', line 62

def to_s
  @value.to_s
end