ActiveSupport::Duration (original) (raw)

Active Support Duration

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)

Namespace

Methods

A

B

E

F

H

I

P

S

T

U

Constants

PARTS = [:years, :months, :weeks, :days, :hours, :minutes, :seconds].freeze
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
SECONDS_PER_DAY = 86400
SECONDS_PER_HOUR = 3600
SECONDS_PER_MINUTE = 60
SECONDS_PER_MONTH = 2629746
SECONDS_PER_WEEK = 604800
SECONDS_PER_YEAR = 31556952
VARIABLE_PARTS = [:years, :months, :weeks, :days].freeze

Attributes

Class Public methods

Creates a new Duration from a seconds value that is converted to the individual parts:

ActiveSupport::Duration.build(31556952).parts # => {:years=>1}
ActiveSupport::Duration.build(2716146).parts  # => {:months=>1, :days=>1}

Source: show | on GitHub

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

Source: show | on GitHub

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

Instance Public methods

Source: show | on GitHub

def %(other) if Duration === other || Scalar === other Duration.build(value % other.value) elsif Numeric === other Duration.build(value % other) else raise_type_error(other) end end

Source: show | on GitHub

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

Source: show | on GitHub

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

Source: show | on GitHub

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

Source: show | on GitHub

def <=>(other) if Duration === other value <=> other.value elsif Numeric === other value <=> other end end

Returns true if other is also a Duration instance with the same value, or if other == value.

Source: show | on GitHub

def ==(other) if Duration === other other.value == value else other == value end end

Calculates a new Time or Date that is as far in the past as this Duration represents.

Source: show | on GitHub

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

Alias for: ago

Returns true if other is also a Duration instance, which has the same parts as this one.

Source: show | on GitHub

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

Returns the amount of days a duration covers as a float

12.hours.in_days # => 0.5

Source: show | on GitHub

def in_days in_seconds / SECONDS_PER_DAY.to_f end

Returns the amount of hours a duration covers as a float

1.day.in_hours # => 24.0

Source: show | on GitHub

def in_hours in_seconds / SECONDS_PER_HOUR.to_f end

Returns the amount of minutes a duration covers as a float

1.day.in_minutes # => 1440.0

Source: show | on GitHub

def in_minutes in_seconds / SECONDS_PER_MINUTE.to_f end

Returns the amount of months a duration covers as a float

9.weeks.in_months # => 2.07

Source: show | on GitHub

def in_months in_seconds / SECONDS_PER_MONTH.to_f end

Returns the amount of weeks a duration covers as a float

2.months.in_weeks # => 8.696

Source: show | on GitHub

def in_weeks in_seconds / SECONDS_PER_WEEK.to_f end

Returns the amount of years a duration covers as a float

30.days.in_years # => 0.082

Source: show | on GitHub

def in_years in_seconds / SECONDS_PER_YEAR.to_f end

Build ISO 8601 Duration string for this duration. The precision parameter can be used to limit seconds’ precision of duration.

Source: show | on GitHub

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

Returns a copy of the parts hash that defines the duration.

5.minutes.parts # => {:minutes=>5}
3.years.parts # => {:years=>3}

Calculates a new Time or Date that is as far in the future as this Duration represents.

Source: show | on GitHub

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

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.

Returns the amount of seconds a duration covers as a string. For more information check to_i method.

1.day.to_s # => "86400"

Alias for: ago