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

Constant Summary collapse

EPOCH =
::Time.utc(2000)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(value, parts) ⇒ Duration

:nodoc:



17
18
19
# File 'lib/active_support/duration.rb', line 17

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:



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

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

Instance Attribute Details

#partsObject

Returns the value of attribute parts.



12
13
14
# File 'lib/active_support/duration.rb', line 12

def parts
  @parts
end

#valueObject

Returns the value of attribute value.



12
13
14
# File 'lib/active_support/duration.rb', line 12

def value
  @value
end

Class Method Details

.===(other) ⇒ Object

:nodoc:



102
103
104
105
106
# File 'lib/active_support/duration.rb', line 102

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.



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

def self.parse(iso8601duration)
  parts = ISO8601Parser.new(iso8601duration).parse!
  new(EPOCH.advance(parts) - EPOCH, parts)
end

Instance Method Details

#+(other) ⇒ Object

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



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

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.



33
34
35
# File 'lib/active_support/duration.rb', line 33

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

#-@Object

:nodoc:



37
38
39
# File 'lib/active_support/duration.rb', line 37

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.



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

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.



117
118
119
# File 'lib/active_support/duration.rb', line 117

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

#as_json(options = nil) ⇒ Object

:nodoc:



130
131
132
# File 'lib/active_support/duration.rb', line 130

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)


94
95
96
# File 'lib/active_support/duration.rb', line 94

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

#hashObject



98
99
100
# File 'lib/active_support/duration.rb', line 98

def hash
  @value.hash
end

#inspectObject

:nodoc:



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

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)


46
47
48
# File 'lib/active_support/duration.rb', line 46

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

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

:nodoc:

Returns:

  • (Boolean)


41
42
43
# File 'lib/active_support/duration.rb', line 41

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.



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

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

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

:nodoc:

Returns:

  • (Boolean)


134
135
136
# File 'lib/active_support/duration.rb', line 134

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.



110
111
112
# File 'lib/active_support/duration.rb', line 110

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.



88
89
90
# File 'lib/active_support/duration.rb', line 88

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"


64
65
66
# File 'lib/active_support/duration.rb', line 64

def to_s
  @value.to_s
end