Class: ActiveSupport::Duration
| Relationships & Source Files | |
| Namespace Children | |
|
Classes:
| |
| Inherits: | Object |
| Defined in: | activesupport/lib/active_support/duration.rb, activesupport/lib/active_support/duration/iso8601_parser.rb, activesupport/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)
Constant Summary
-
PARTS =
# File 'activesupport/lib/active_support/duration.rb', line 134[:years, :months, :weeks, :days, :hours, :minutes, :seconds].freeze
-
PARTS_IN_SECONDS =
# File 'activesupport/lib/active_support/duration.rb', line 124{ 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 -
SECONDS_PER_DAY =
# File 'activesupport/lib/active_support/duration.rb', line 11986400 -
SECONDS_PER_HOUR =
# File 'activesupport/lib/active_support/duration.rb', line 1183600 -
SECONDS_PER_MINUTE =
# File 'activesupport/lib/active_support/duration.rb', line 11760 -
SECONDS_PER_MONTH =
# File 'activesupport/lib/active_support/duration.rb', line 121
1/12 of a gregorian year
2629746 -
SECONDS_PER_WEEK =
# File 'activesupport/lib/active_support/duration.rb', line 120604800 -
SECONDS_PER_YEAR =
# File 'activesupport/lib/active_support/duration.rb', line 122
length of a gregorian year (365.2425 days)
31556952 -
VARIABLE_PARTS =
# File 'activesupport/lib/active_support/duration.rb', line 135[:years, :months, :weeks, :days].freeze
Class Method Summary
-
.build(value)
Creates a new
Durationfrom a seconds value that is converted to the individual parts: -
.parse(iso8601duration)
Creates a new
Durationfrom string formatted according to ISO 8601Duration. - .calculate_total_seconds(parts) private
- .===(other) Internal use only
- .days(value) Internal use only
- .hours(value) Internal use only
- .minutes(value) Internal use only
- .months(value) Internal use only
- .new(value, parts, variable = nil) ⇒ Duration constructor Internal use only
- .seconds(value) Internal use only
- .weeks(value) Internal use only
- .years(value) Internal use only
Instance Attribute Summary
- #value readonly
- #variable? ⇒ Boolean readonly Internal use only
Instance Method Summary
-
#%(other)
Returns the modulo of this
Durationby anotherDurationor::Numeric. -
#*(other)
Multiplies this
Durationby a::Numericand returns a newDuration. -
#+(other)
Adds another
Durationor a::Numericto thisDuration. -
#-(other)
Subtracts another
Durationor a::Numericfrom thisDuration. -
#/(other)
Divides this
Durationby a::Numericand returns a newDuration. -
#<=>(other)
Compares one
Durationwith another or a::Numericto thisDuration. -
#==(other)
Returns
trueifotheris also aDurationinstance with the same #value, or ifother == value. -
#after(time = ::Time.current)
Alias for #since.
- #ago(time = ::Time.current) (also: #until, #before)
-
#before(time = ::Time.current)
Alias for #ago.
-
#eql?(other) ⇒ Boolean
Returns
trueifotheris also aDurationinstance, which has the same parts as this one. -
#from_now(time = ::Time.current)
Alias for #since.
- #hash
-
#in_days
Returns the amount of days a duration covers as a float.
-
#in_hours
Returns the amount of hours a duration covers as a float.
-
#in_minutes
Returns the amount of minutes a duration covers as a float.
-
#in_months
Returns the amount of months a duration covers as a float.
-
#in_seconds
Alias for #to_i.
-
#in_weeks
Returns the amount of weeks a duration covers as a float.
-
#in_years
Returns the amount of years a duration covers as a float.
-
#iso8601(precision: nil)
Build ISO 8601
Durationstring for this duration. -
#kind_of?(klass)
Alias for #is_a?.
-
#parts
Returns a copy of the parts hash that defines the duration.
- #since(time = ::Time.current) (also: #from_now, #after)
-
#to_i
(also: #in_seconds)
Returns the number of seconds that this
Durationrepresents. -
#to_s
Returns the amount of seconds a duration covers as a string.
-
#until(time = ::Time.current)
Alias for #ago.
- #method_missing private
- #raise_type_error(other) private
- #respond_to_missing?(method, _) ⇒ Boolean private
- #sum(sign, time = ::Time.current) private
- #+@ Internal use only
- #-@ Internal use only
- #_parts Internal use only
- #as_json(options = nil) Internal use only
- #coerce(other) Internal use only
- #encode_with(coder) Internal use only
- #init_with(coder) Internal use only
- #inspect Internal use only
- #instance_of?(klass) ⇒ Boolean Internal use only
- #is_a?(klass) ⇒ Boolean (also: #kind_of?) Internal use only
Constructor Details
.new(value, parts, variable = nil) ⇒ Duration
# File 'activesupport/lib/active_support/duration.rb', line 232
def initialize(value, parts, variable = nil) # :nodoc: @value, @parts = value, parts @parts.reject! { |k, v| v.zero? } unless value == 0 @parts.freeze @variable = variable if @variable.nil? @variable = @parts.any? { |part, _| VARIABLE_PARTS.include?(part) } end end
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing (private)
[ GitHub ]# File 'activesupport/lib/active_support/duration.rb', line 542
def method_missing(...) value.public_send(...) end
Class Method Details
.===(other)
# File 'activesupport/lib/active_support/duration.rb', line 153
def ===(other) # :nodoc: other.is_a?(Duration) rescue ::NoMethodError false end
.build(value)
Creates a new Duration from a seconds value that is converted
to the individual parts:
<code>build</code>(31556952).parts # => {:years=>1}
<code>build</code>(2716146).parts # => {:months=>1, :days=>1}
# File 'activesupport/lib/active_support/duration.rb', line 195
def build(value) unless value.is_a?(::Numeric) raise TypeError, "can't build an #{self.name} from a #{value.class.name}" end parts = {} remainder_sign = value <=> 0 remainder = value.round(9).abs variable = false PARTS.each do |part| unless part == :seconds part_in_seconds = PARTS_IN_SECONDS[part] parts[part] = remainder.div(part_in_seconds) * remainder_sign remainder %= part_in_seconds unless parts[part].zero? variable ||= VARIABLE_PARTS.include?(part) end end end unless value == 0 parts[:seconds] = remainder * remainder_sign new(value, parts, variable) end
.calculate_total_seconds(parts) (private)
[ GitHub ]# File 'activesupport/lib/active_support/duration.rb', line 223
def calculate_total_seconds(parts) parts.inject(0) do |total, (part, value)| total + value * PARTS_IN_SECONDS[part] end end
.days(value)
# File 'activesupport/lib/active_support/duration.rb', line 171
def days(value) # :nodoc: new(value * SECONDS_PER_DAY, { days: value }, true) end
.hours(value)
# File 'activesupport/lib/active_support/duration.rb', line 167
def hours(value) # :nodoc: new(value * SECONDS_PER_HOUR, { hours: value }, false) end
.minutes(value)
# File 'activesupport/lib/active_support/duration.rb', line 163
def minutes(value) # :nodoc: new(value * SECONDS_PER_MINUTE, { minutes: value }, false) end
.months(value)
# File 'activesupport/lib/active_support/duration.rb', line 179
def months(value) # :nodoc: new(value * SECONDS_PER_MONTH, { months: value }, true) end
.parse(iso8601duration)
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 Duration::ISO8601Parser::ParsingError.
# File 'activesupport/lib/active_support/duration.rb', line 148
def parse(iso8601duration) parts = ISO8601Parser.new(iso8601duration).parse! new(calculate_total_seconds(parts), parts) end
.seconds(value)
.weeks(value)
# File 'activesupport/lib/active_support/duration.rb', line 175
def weeks(value) # :nodoc: new(value * SECONDS_PER_WEEK, { weeks: value }, true) end
.years(value)
# File 'activesupport/lib/active_support/duration.rb', line 183
def years(value) # :nodoc: new(value * SECONDS_PER_YEAR, { years: value }, true) end
Instance Attribute Details
#value (readonly)
[ GitHub ]# File 'activesupport/lib/active_support/duration.rb', line 137
attr_reader :value
#variable? ⇒ Boolean (readonly)
# File 'activesupport/lib/active_support/duration.rb', line 503
def variable? # :nodoc: @variable end
Instance Method Details
#%(other)
#*(other)
Multiplies this Duration by a ::Numeric and returns a new Duration.
# File 'activesupport/lib/active_support/duration.rb', line 295
def *(other) if Scalar === other || Duration === other Duration.new(value * other.value, @parts.transform_values { |number| number * other.value }, @variable || other.variable?) elsif Numeric === other Duration.new(value * other, @parts.transform_values { |number| number * other }, @variable) else raise_type_error(other) end end
#+(other)
[ GitHub ]# File 'activesupport/lib/active_support/duration.rb', line 276
def +(other) if Duration === other parts = @parts.merge(other._parts) do |_key, value, other_value| value + other_value end Duration.new(value + other.value, parts, @variable || other.variable?) else seconds = @parts.fetch(:seconds, 0) + other Duration.new(value + other, @parts.merge(seconds: seconds), @variable) end end
#+@
# File 'activesupport/lib/active_support/duration.rb', line 334
def +@ # :nodoc: self end
#-(other)
# File 'activesupport/lib/active_support/duration.rb', line 290
def -(other) self + (-other) end
#-@
#/(other)
Divides this Duration by a ::Numeric and returns a new Duration.
# File 'activesupport/lib/active_support/duration.rb', line 306
def /(other) if Scalar === other Duration.new(value / other.value, @parts.transform_values { |number| number / other.value }, @variable) elsif Duration === other value / other.value elsif Numeric === other Duration.new(value / other, @parts.transform_values { |number| number / other }, @variable) else raise_type_error(other) end end
#<=>(other)
#==(other)
Returns true if other is also a Duration instance with the
same #value, or if other == value.
#_parts
# File 'activesupport/lib/active_support/duration.rb', line 507
def _parts # :nodoc: @parts end
#after(time = ::Time.current)
Alias for #since.
# File 'activesupport/lib/active_support/duration.rb', line 466
alias :after :since
#ago(time = ::Time.current) Also known as: #until, #before
[ GitHub ]#as_json(options = nil)
# File 'activesupport/lib/active_support/duration.rb', line 485
def as_json( = nil) # :nodoc: to_i end
#before(time = ::Time.current)
Alias for #ago.
# File 'activesupport/lib/active_support/duration.rb', line 474
alias :before :ago
#coerce(other)
#encode_with(coder)
# File 'activesupport/lib/active_support/duration.rb', line 493
def encode_with(coder) # :nodoc: coder.map = { "value" => @value, "parts" => @parts } end
#eql?(other) ⇒ Boolean
Returns true if other is also a Duration instance, which has the
same parts as this one.
#from_now(time = ::Time.current)
Alias for #since.
# File 'activesupport/lib/active_support/duration.rb', line 465
alias :from_now :since
#hash
[ GitHub ]# File 'activesupport/lib/active_support/duration.rb', line 456
def hash @value.hash end
#in_days
Returns the amount of days a duration covers as a float
12.hours.in_days # => 0.5
# File 'activesupport/lib/active_support/duration.rb', line 419
def in_days value / SECONDS_PER_DAY.to_f end
#in_hours
Returns the amount of hours a duration covers as a float
1.day.in_hours # => 24.0
# File 'activesupport/lib/active_support/duration.rb', line 410
def in_hours value / SECONDS_PER_HOUR.to_f end
#in_minutes
Returns the amount of minutes a duration covers as a float
1.day.in_minutes # => 1440.0
# File 'activesupport/lib/active_support/duration.rb', line 401
def in_minutes value / SECONDS_PER_MINUTE.to_f end
#in_months
Returns the amount of months a duration covers as a float
9.weeks.in_months # => 2.07
# File 'activesupport/lib/active_support/duration.rb', line 437
def in_months value / SECONDS_PER_MONTH.to_f end
#in_seconds
Alias for #to_i.
# File 'activesupport/lib/active_support/duration.rb', line 394
alias :in_seconds :to_i
#in_weeks
Returns the amount of weeks a duration covers as a float
2.months.in_weeks # => 8.696
# File 'activesupport/lib/active_support/duration.rb', line 428
def in_weeks value / SECONDS_PER_WEEK.to_f end
#in_years
Returns the amount of years a duration covers as a float
30.days.in_years # => 0.082
# File 'activesupport/lib/active_support/duration.rb', line 446
def in_years value / SECONDS_PER_YEAR.to_f end
#init_with(coder)
# File 'activesupport/lib/active_support/duration.rb', line 489
def init_with(coder) # :nodoc: initialize(coder["value"], coder["parts"]) end
#inspect
#instance_of?(klass) ⇒ Boolean
# File 'activesupport/lib/active_support/duration.rb', line 343
def instance_of?(klass) # :nodoc: Duration == klass || value.instance_of?(klass) end
#is_a?(klass) ⇒ Boolean
Also known as: #kind_of?
# File 'activesupport/lib/active_support/duration.rb', line 338
def is_a?(klass) # :nodoc: Duration == klass || value.is_a?(klass) end
#iso8601(precision: nil)
Build ISO 8601 Duration string for this duration.
The precision parameter can be used to limit seconds' precision of duration.
# File 'activesupport/lib/active_support/duration.rb', line 499
def iso8601(precision: nil) ISO8601Serializer.new(self, precision: precision).serialize end
#kind_of?(klass)
Alias for #is_a?.
# File 'activesupport/lib/active_support/duration.rb', line 341
alias :kind_of? :is_a?
#parts
# File 'activesupport/lib/active_support/duration.rb', line 249
def parts @parts.dup end
#raise_type_error(other) (private)
# File 'activesupport/lib/active_support/duration.rb', line 546
def raise_type_error(other) raise TypeError, "no implicit conversion of #{other.class} into #{self.class}" end
#respond_to_missing?(method, _) ⇒ Boolean (private)
# File 'activesupport/lib/active_support/duration.rb', line 538
def respond_to_missing?(method, _) value.respond_to?(method) end
#since(time = ::Time.current) Also known as: #from_now, #after
[ GitHub ]#sum(sign, time = ::Time.current) (private)
[ GitHub ]# File 'activesupport/lib/active_support/duration.rb', line 512
def sum(sign, time = ::Time.current) unless time.acts_like?(:time) || time.acts_like?(:date) raise ::ArgumentError, "expected a time or date, got #{time.inspect}" end if @parts.empty? time.since(sign * value) else @parts.each do |type, number| t = time time = if type == :seconds t.since(sign * number) elsif type == :minutes t.since(sign * number * 60) elsif type == :hours t.since(sign * number * 3600) else t.advance(type => sign * number) end end time end end
#to_i Also known as: #in_seconds
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.
# File 'activesupport/lib/active_support/duration.rb', line 391
def to_i @value.to_i end
#to_s
Returns the amount of seconds a duration covers as a string. For more information check to_i method.
1.day.to_s # => "86400"
# File 'activesupport/lib/active_support/duration.rb', line 363
def to_s @value.to_s end
#until(time = ::Time.current)
Alias for #ago.
# File 'activesupport/lib/active_support/duration.rb', line 473
alias :until :ago