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:
178 179 180 181 |
# File 'lib/active_support/duration.rb', line 178 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)
367 368 369 |
# File 'lib/active_support/duration.rb', line 367 def method_missing(method, *args, &block) value.send(method, *args, &block) end |
Instance Attribute Details
#parts ⇒ Object
Returns the value of attribute parts.
119 120 121 |
# File 'lib/active_support/duration.rb', line 119 def parts @parts end |
#value ⇒ Object
Returns the value of attribute value.
119 120 121 |
# File 'lib/active_support/duration.rb', line 119 def value @value end |
Class Method Details
.===(other) ⇒ Object
:nodoc:
135 136 137 138 139 |
# File 'lib/active_support/duration.rb', line 135 def ===(other) #:nodoc: other.is_a?(Duration) rescue ::NoMethodError false end |
.days(value) ⇒ Object
:nodoc:
153 154 155 |
# File 'lib/active_support/duration.rb', line 153 def days(value) #:nodoc: new(value * SECONDS_PER_DAY, [[:days, value]]) end |
.hours(value) ⇒ Object
:nodoc:
149 150 151 |
# File 'lib/active_support/duration.rb', line 149 def hours(value) #:nodoc: new(value * SECONDS_PER_HOUR, [[:hours, value]]) end |
.minutes(value) ⇒ Object
:nodoc:
145 146 147 |
# File 'lib/active_support/duration.rb', line 145 def minutes(value) #:nodoc: new(value * SECONDS_PER_MINUTE, [[:minutes, value]]) end |
.months(value) ⇒ Object
:nodoc:
161 162 163 |
# File 'lib/active_support/duration.rb', line 161 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
.
130 131 132 133 |
# File 'lib/active_support/duration.rb', line 130 def parse(iso8601duration) parts = ISO8601Parser.new(iso8601duration).parse! new(calculate_total_seconds(parts), parts) end |
.seconds(value) ⇒ Object
:nodoc:
141 142 143 |
# File 'lib/active_support/duration.rb', line 141 def seconds(value) #:nodoc: new(value, [[:seconds, value]]) end |
.weeks(value) ⇒ Object
:nodoc:
157 158 159 |
# File 'lib/active_support/duration.rb', line 157 def weeks(value) #:nodoc: new(value * SECONDS_PER_WEEK, [[:weeks, value]]) end |
.years(value) ⇒ Object
:nodoc:
165 166 167 |
# File 'lib/active_support/duration.rb', line 165 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.
223 224 225 226 227 228 229 230 231 |
# File 'lib/active_support/duration.rb', line 223 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.
203 204 205 206 207 208 209 210 211 212 213 214 |
# File 'lib/active_support/duration.rb', line 203 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.
218 219 220 |
# File 'lib/active_support/duration.rb', line 218 def -(other) self + (-other) end |
#-@ ⇒ Object
:nodoc:
244 245 246 |
# File 'lib/active_support/duration.rb', line 244 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.
234 235 236 237 238 239 240 241 242 |
# File 'lib/active_support/duration.rb', line 234 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.
193 194 195 196 197 198 199 |
# File 'lib/active_support/duration.rb', line 193 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
.
259 260 261 262 263 264 265 |
# File 'lib/active_support/duration.rb', line 259 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.
319 320 321 |
# File 'lib/active_support/duration.rb', line 319 def ago(time = ::Time.current) sum(-1, time) end |
#as_json(options = nil) ⇒ Object
:nodoc:
333 334 335 |
# File 'lib/active_support/duration.rb', line 333 def as_json( = nil) #:nodoc: to_i end |
#coerce(other) ⇒ Object
:nodoc:
183 184 185 186 187 188 189 |
# File 'lib/active_support/duration.rb', line 183 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.
301 302 303 |
# File 'lib/active_support/duration.rb', line 301 def eql?(other) Duration === other && other.value.eql?(value) end |
#hash ⇒ Object
305 306 307 |
# File 'lib/active_support/duration.rb', line 305 def hash @value.hash end |
#inspect ⇒ Object
:nodoc:
325 326 327 328 329 330 331 |
# File 'lib/active_support/duration.rb', line 325 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:
253 254 255 |
# File 'lib/active_support/duration.rb', line 253 def instance_of?(klass) # :nodoc: Duration == klass || value.instance_of?(klass) end |
#is_a?(klass) ⇒ Boolean Also known as: kind_of?
:nodoc:
248 249 250 |
# File 'lib/active_support/duration.rb', line 248 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.
343 344 345 |
# File 'lib/active_support/duration.rb', line 343 def iso8601(precision: nil) ISO8601Serializer.new(self, precision: precision).serialize end |
#respond_to_missing?(method, include_private = false) ⇒ Boolean
:nodoc:
337 338 339 |
# File 'lib/active_support/duration.rb', line 337 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.
311 312 313 |
# File 'lib/active_support/duration.rb', line 311 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.
295 296 297 |
# File 'lib/active_support/duration.rb', line 295 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"
271 272 273 |
# File 'lib/active_support/duration.rb', line 271 def to_s @value.to_s end |