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

SECONDS_PER_MINUTE =
60
SECONDS_PER_HOUR =
3600
SECONDS_PER_DAY =
86400
SECONDS_PER_WEEK =
604800
SECONDS_PER_MONTH =

30 days

2592000
SECONDS_PER_YEAR =

length of a julian year (365.2425 days)

31557600
PARTS_IN_SECONDS =
{
  seconds: 1,
  minutes: SECONDS_PER_MINUTE,
  hours:   SECONDS_PER_HOUR,
  days:    SECONDS_PER_DAY,
  weeks:   SECONDS_PER_WEEK,
  months:  SECONDS_PER_MONTH,
  years:   SECONDS_PER_YEAR
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(value, parts) ⇒ Duration

:nodoc:



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

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:



231
232
233
# File 'lib/active_support/duration.rb', line 231

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

Instance Attribute Details

#partsObject

Returns the value of attribute parts.



27
28
29
# File 'lib/active_support/duration.rb', line 27

def parts
  @parts
end

#valueObject

Returns the value of attribute value.



27
28
29
# File 'lib/active_support/duration.rb', line 27

def value
  @value
end

Class Method Details

.===(other) ⇒ Object

:nodoc:



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

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

.days(value) ⇒ Object

:nodoc:



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

def days(value) #:nodoc:
  new(value * SECONDS_PER_DAY, [[:days, value]])
end

.hours(value) ⇒ Object

:nodoc:



57
58
59
# File 'lib/active_support/duration.rb', line 57

def hours(value) #:nodoc:
  new(value * SECONDS_PER_HOUR, [[:hours, value]])
end

.minutes(value) ⇒ Object

:nodoc:



53
54
55
# File 'lib/active_support/duration.rb', line 53

def minutes(value) #:nodoc:
  new(value * SECONDS_PER_MINUTE, [[:minutes, value]])
end

.months(value) ⇒ Object

:nodoc:



69
70
71
# File 'lib/active_support/duration.rb', line 69

def months(value) #:nodoc:
  new(value * SECONDS_PER_MONTH, [[:months, value]])
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.



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

def parse(iso8601duration)
  parts = ISO8601Parser.new(iso8601duration).parse!
  new(calculate_total_seconds(parts), parts)
end

.seconds(value) ⇒ Object

:nodoc:



49
50
51
# File 'lib/active_support/duration.rb', line 49

def seconds(value) #:nodoc:
  new(value, [[:seconds, value]])
end

.weeks(value) ⇒ Object

:nodoc:



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

def weeks(value) #:nodoc:
  new(value * SECONDS_PER_WEEK, [[:weeks, value]])
end

.years(value) ⇒ Object

:nodoc:



73
74
75
# File 'lib/active_support/duration.rb', line 73

def years(value) #:nodoc:
  new(value * SECONDS_PER_YEAR, [[:years, value]])
end

Instance Method Details

#+(other) ⇒ Object

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



92
93
94
95
96
97
98
# File 'lib/active_support/duration.rb', line 92

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.



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

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

#-@Object

:nodoc:



106
107
108
# File 'lib/active_support/duration.rb', line 106

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.



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

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.



180
181
182
# File 'lib/active_support/duration.rb', line 180

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

#as_json(options = nil) ⇒ Object

:nodoc:



193
194
195
# File 'lib/active_support/duration.rb', line 193

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)


163
164
165
# File 'lib/active_support/duration.rb', line 163

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

#hashObject



167
168
169
# File 'lib/active_support/duration.rb', line 167

def hash
  @value.hash
end

#inspectObject

:nodoc:



185
186
187
188
189
190
191
# File 'lib/active_support/duration.rb', line 185

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)


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

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

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

:nodoc:

Returns:

  • (Boolean)


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

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.



203
204
205
# File 'lib/active_support/duration.rb', line 203

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

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

:nodoc:

Returns:

  • (Boolean)


197
198
199
# File 'lib/active_support/duration.rb', line 197

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.



173
174
175
# File 'lib/active_support/duration.rb', line 173

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.



157
158
159
# File 'lib/active_support/duration.rb', line 157

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"


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

def to_s
  @value.to_s
end