Class: ActiveSupport::Duration
- 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, Scalar
Constant Summary collapse
- SECONDS_PER_MINUTE =
60
- SECONDS_PER_HOUR =
3600
- SECONDS_PER_DAY =
86400
- SECONDS_PER_WEEK =
604800
- SECONDS_PER_MONTH =
1/12 of a gregorian year
2629746
- SECONDS_PER_YEAR =
length of a gregorian year (365.2425 days)
31556952
- 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
-
#parts ⇒ Object
Returns the value of attribute parts.
-
#value ⇒ Object
Returns the value of attribute value.
Class Method Summary collapse
-
.===(other) ⇒ Object
:nodoc:.
-
.days(value) ⇒ Object
:nodoc:.
-
.hours(value) ⇒ Object
:nodoc:.
-
.minutes(value) ⇒ Object
:nodoc:.
-
.months(value) ⇒ Object
:nodoc:.
-
.parse(iso8601duration) ⇒ Object
Creates a new Duration from string formatted according to ISO 8601 Duration.
-
.seconds(value) ⇒ Object
:nodoc:.
-
.weeks(value) ⇒ Object
:nodoc:.
-
.years(value) ⇒ Object
:nodoc:.
Instance Method Summary collapse
-
#*(other) ⇒ Object
Multiplies this Duration by a Numeric and returns a new Duration.
-
#+(other) ⇒ Object
Adds another Duration or a Numeric to this Duration.
-
#-(other) ⇒ Object
Subtracts another Duration or a Numeric from this Duration.
-
#-@ ⇒ Object
:nodoc:.
-
#/(other) ⇒ Object
Divides this Duration by a Numeric and returns a new Duration.
-
#<=>(other) ⇒ Object
Compares one Duration with another or a Numeric to this Duration.
-
#==(other) ⇒ Object
Returns
true
ifother
is also a Duration instance with the samevalue
, or ifother == value
. -
#ago(time = ::Time.current) ⇒ Object
(also: #until, #before)
Calculates a new Time or Date that is as far in the past as this Duration represents.
-
#as_json(options = nil) ⇒ Object
:nodoc:.
-
#coerce(other) ⇒ Object
:nodoc:.
-
#eql?(other) ⇒ Boolean
Returns
true
ifother
is also a Duration instance, which has the same parts as this one. - #hash ⇒ Object
-
#initialize(value, parts) ⇒ Duration
constructor
:nodoc:.
-
#inspect ⇒ Object
:nodoc:.
-
#instance_of?(klass) ⇒ Boolean
:nodoc:.
-
#is_a?(klass) ⇒ Boolean
(also: #kind_of?)
:nodoc:.
-
#iso8601(precision: nil) ⇒ Object
Build ISO 8601 Duration string for this duration.
-
#respond_to_missing?(method, include_private = false) ⇒ Boolean
:nodoc:.
-
#since(time = ::Time.current) ⇒ Object
(also: #from_now, #after)
Calculates a new Time or Date that is as far in the future as this Duration represents.
-
#to_i ⇒ Object
Returns the number of seconds that this Duration represents.
-
#to_s ⇒ Object
Returns the amount of seconds a duration covers as a string.
Constructor Details
#initialize(value, parts) ⇒ Duration
:nodoc:
149 150 151 152 |
# File 'lib/active_support/duration.rb', line 149 def initialize(value, parts) #:nodoc: @value, @parts = value, parts.to_h @parts.default = 0 end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args, &block) ⇒ Object (private)
338 339 340 |
# File 'lib/active_support/duration.rb', line 338 def method_missing(method, *args, &block) value.send(method, *args, &block) end |
Instance Attribute Details
#parts ⇒ Object
Returns the value of attribute parts.
90 91 92 |
# File 'lib/active_support/duration.rb', line 90 def parts @parts end |
#value ⇒ Object
Returns the value of attribute value.
90 91 92 |
# File 'lib/active_support/duration.rb', line 90 def value @value end |
Class Method Details
.===(other) ⇒ Object
:nodoc:
106 107 108 109 110 |
# File 'lib/active_support/duration.rb', line 106 def ===(other) #:nodoc: other.is_a?(Duration) rescue ::NoMethodError false end |
.days(value) ⇒ Object
:nodoc:
124 125 126 |
# File 'lib/active_support/duration.rb', line 124 def days(value) #:nodoc: new(value * SECONDS_PER_DAY, [[:days, value]]) end |
.hours(value) ⇒ Object
:nodoc:
120 121 122 |
# File 'lib/active_support/duration.rb', line 120 def hours(value) #:nodoc: new(value * SECONDS_PER_HOUR, [[:hours, value]]) end |
.minutes(value) ⇒ Object
:nodoc:
116 117 118 |
# File 'lib/active_support/duration.rb', line 116 def minutes(value) #:nodoc: new(value * SECONDS_PER_MINUTE, [[:minutes, value]]) end |
.months(value) ⇒ Object
:nodoc:
132 133 134 |
# File 'lib/active_support/duration.rb', line 132 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
.
101 102 103 104 |
# File 'lib/active_support/duration.rb', line 101 def parse(iso8601duration) parts = ISO8601Parser.new(iso8601duration).parse! new(calculate_total_seconds(parts), parts) end |
.seconds(value) ⇒ Object
:nodoc:
112 113 114 |
# File 'lib/active_support/duration.rb', line 112 def seconds(value) #:nodoc: new(value, [[:seconds, value]]) end |
.weeks(value) ⇒ Object
:nodoc:
128 129 130 |
# File 'lib/active_support/duration.rb', line 128 def weeks(value) #:nodoc: new(value * SECONDS_PER_WEEK, [[:weeks, value]]) end |
.years(value) ⇒ Object
:nodoc:
136 137 138 |
# File 'lib/active_support/duration.rb', line 136 def years(value) #:nodoc: new(value * SECONDS_PER_YEAR, [[:years, value]]) end |
Instance Method Details
#*(other) ⇒ Object
Multiplies this Duration by a Numeric and returns a new Duration.
194 195 196 197 198 199 200 201 202 |
# File 'lib/active_support/duration.rb', line 194 def *(other) if Scalar === other || Duration === other Duration.new(value * other.value, parts.map { |type, number| [type, number * other.value] }) elsif Numeric === other Duration.new(value * other, parts.map { |type, number| [type, number * other] }) else raise_type_error(other) end end |
#+(other) ⇒ Object
Adds another Duration or a Numeric to this Duration. Numeric values are treated as seconds.
174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/active_support/duration.rb', line 174 def +(other) if Duration === other parts = @parts.dup other.parts.each do |(key, value)| parts[key] += value end Duration.new(value + other.value, parts) else seconds = @parts[:seconds] + other Duration.new(value + other, @parts.merge(seconds: seconds)) end end |
#-(other) ⇒ Object
Subtracts another Duration or a Numeric from this Duration. Numeric values are treated as seconds.
189 190 191 |
# File 'lib/active_support/duration.rb', line 189 def -(other) self + (-other) end |
#-@ ⇒ Object
:nodoc:
215 216 217 |
# File 'lib/active_support/duration.rb', line 215 def -@ #:nodoc: Duration.new(-value, parts.map { |type, number| [type, -number] }) end |
#/(other) ⇒ Object
Divides this Duration by a Numeric and returns a new Duration.
205 206 207 208 209 210 211 212 213 |
# File 'lib/active_support/duration.rb', line 205 def /(other) if Scalar === other || Duration === other Duration.new(value / other.value, parts.map { |type, number| [type, number / other.value] }) elsif Numeric === other Duration.new(value / other, parts.map { |type, number| [type, number / other] }) else raise_type_error(other) end end |
#<=>(other) ⇒ Object
Compares one Duration with another or a Numeric to this Duration. Numeric values are treated as seconds.
164 165 166 167 168 169 170 |
# File 'lib/active_support/duration.rb', line 164 def <=>(other) if Duration === other value <=> other.value elsif Numeric === other value <=> other end end |
#==(other) ⇒ Object
Returns true
if other
is also a Duration instance with the same value
, or if other == value
.
230 231 232 233 234 235 236 |
# File 'lib/active_support/duration.rb', line 230 def ==(other) if Duration === other other.value == value else other == value end end |
#ago(time = ::Time.current) ⇒ Object Also known as: until, before
Calculates a new Time or Date that is as far in the past as this Duration represents.
290 291 292 |
# File 'lib/active_support/duration.rb', line 290 def ago(time = ::Time.current) sum(-1, time) end |
#as_json(options = nil) ⇒ Object
:nodoc:
304 305 306 |
# File 'lib/active_support/duration.rb', line 304 def as_json( = nil) #:nodoc: to_i end |
#coerce(other) ⇒ Object
:nodoc:
154 155 156 157 158 159 160 |
# File 'lib/active_support/duration.rb', line 154 def coerce(other) #:nodoc: if Scalar === other [other, self] else [Scalar.new(other), self] end end |
#eql?(other) ⇒ Boolean
Returns true
if other
is also a Duration instance, which has the same parts as this one.
272 273 274 |
# File 'lib/active_support/duration.rb', line 272 def eql?(other) Duration === other && other.value.eql?(value) end |
#hash ⇒ Object
276 277 278 |
# File 'lib/active_support/duration.rb', line 276 def hash @value.hash end |
#inspect ⇒ Object
:nodoc:
296 297 298 299 300 301 302 |
# File 'lib/active_support/duration.rb', line 296 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:
224 225 226 |
# File 'lib/active_support/duration.rb', line 224 def instance_of?(klass) # :nodoc: Duration == klass || value.instance_of?(klass) end |
#is_a?(klass) ⇒ Boolean Also known as: kind_of?
:nodoc:
219 220 221 |
# File 'lib/active_support/duration.rb', line 219 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.
314 315 316 |
# File 'lib/active_support/duration.rb', line 314 def iso8601(precision: nil) ISO8601Serializer.new(self, precision: precision).serialize end |
#respond_to_missing?(method, include_private = false) ⇒ Boolean
:nodoc:
308 309 310 |
# File 'lib/active_support/duration.rb', line 308 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, after
Calculates a new Time or Date that is as far in the future as this Duration represents.
282 283 284 |
# File 'lib/active_support/duration.rb', line 282 def since(time = ::Time.current) sum(1, time) end |
#to_i ⇒ Object
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 1/12 of year and years are 365.2425 days:
# equivalent to (1.year / 12).to_i
1.month.to_i # => 2629746
# equivalent to 365.2425.days.to_i
1.year.to_i # => 31556952
In such cases, Ruby’s core Date and Time should be used for precision date and time arithmetic.
266 267 268 |
# File 'lib/active_support/duration.rb', line 266 def to_i @value.to_i end |
#to_s ⇒ Object
Returns the amount of seconds a duration covers as a string. For more information check to_i method.
1.day.to_s # => "86400"
242 243 244 |
# File 'lib/active_support/duration.rb', line 242 def to_s @value.to_s end |