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
Class
Methods
- %
- *
- +
- -
- /
- <=>
- ==
- after
- ago
- before
- build
- eql?
- from_now
- hash
- in_days
- in_hours
- in_minutes
- in_months
- in_seconds
- in_weeks
- in_years
- iso8601
- parse
- since
- to_i
- to_s
- until
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 |
Attributes
[RW] | parts | |
[RW] | value |
Class Public methods
build(value)
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 code
# File activesupport/lib/active_support/duration.rb, line 183
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
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
end
end unless value == 0
parts[:seconds] = remainder * remainder_sign
new(value, parts)
end
🔎 See on GitHub
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 ActiveSupport::Duration::ISO8601Parser::ParsingError
.
📝 Source code
# File activesupport/lib/active_support/duration.rb, line 138
def parse(iso8601duration)
parts = ISO8601Parser.new(iso8601duration).parse!
new(calculate_total_seconds(parts), parts)
end
🔎 See on GitHub
Instance Public methods
%(other)
Returns the modulo of this Duration
by another Duration
or Numeric
. Numeric
values are treated as seconds.
📝 Source code
# File activesupport/lib/active_support/duration.rb, line 285
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
🔎 See on GitHub
*(other)
📝 Source code
# File activesupport/lib/active_support/duration.rb, line 260
def *(other)
if Scalar === other || Duration === other
Duration.new(value * other.value, parts.transform_values { |number| number * other.value })
elsif Numeric === other
Duration.new(value * other, parts.transform_values { |number| number * other })
else
raise_type_error(other)
end
end
🔎 See on GitHub
+(other)
📝 Source code
# File activesupport/lib/active_support/duration.rb, line 241
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)
else
seconds = @parts.fetch(:seconds, 0) + other
Duration.new(value + other, @parts.merge(seconds: seconds))
end
end
🔎 See on GitHub
-(other)
📝 Source code
# File activesupport/lib/active_support/duration.rb, line 255
def -(other)
self + (-other)
end
🔎 See on GitHub
/(other)
📝 Source code
# File activesupport/lib/active_support/duration.rb, line 271
def /(other)
if Scalar === other
Duration.new(value / other.value, parts.transform_values { |number| number / other.value })
elsif Duration === other
value / other.value
elsif Numeric === other
Duration.new(value / other, parts.transform_values { |number| number / other })
else
raise_type_error(other)
end
end
🔎 See on GitHub
<=>(other)
Compares one Duration
with another or a Numeric
to this Duration
. Numeric
values are treated as seconds.
📝 Source code
# File activesupport/lib/active_support/duration.rb, line 231
def <=>(other)
if Duration === other
value <=> other.value
elsif Numeric === other
value <=> other
end
end
🔎 See on GitHub
==(other)
Returns true
if other
is also a Duration
instance with the same value
, or if other == value
.
📝 Source code
# File activesupport/lib/active_support/duration.rb, line 314
def ==(other)
if Duration === other
other.value == value
else
other == value
end
end
🔎 See on GitHub
ago(time = ::Time.current)
📝 Source code
# File activesupport/lib/active_support/duration.rb, line 417
def ago(time = ::Time.current)
sum(-1, time)
end
🔎 See on GitHub
eql?(other)
Returns true
if other
is also a Duration
instance, which has the same parts as this one.
📝 Source code
# File activesupport/lib/active_support/duration.rb, line 399
def eql?(other)
Duration === other && other.value.eql?(value)
end
🔎 See on GitHub
hash()
📝 Source code
# File activesupport/lib/active_support/duration.rb, line 403
def hash
@value.hash
end
🔎 See on GitHub
in_days()
Returns the amount of days a duration covers as a float
12.hours.in_days # => 0.5
📝 Source code
# File activesupport/lib/active_support/duration.rb, line 372
def in_days
in_seconds / SECONDS_PER_DAY.to_f
end
🔎 See on GitHub
in_hours()
Returns the amount of hours a duration covers as a float
1.day.in_hours # => 24.0
📝 Source code
# File activesupport/lib/active_support/duration.rb, line 365
def in_hours
in_seconds / SECONDS_PER_HOUR.to_f
end
🔎 See on GitHub
in_minutes()
Returns the amount of minutes a duration covers as a float
1.day.in_minutes # => 1440.0
📝 Source code
# File activesupport/lib/active_support/duration.rb, line 358
def in_minutes
in_seconds / SECONDS_PER_MINUTE.to_f
end
🔎 See on GitHub
in_months()
Returns the amount of months a duration covers as a float
9.weeks.in_months # => 2.07
📝 Source code
# File activesupport/lib/active_support/duration.rb, line 386
def in_months
in_seconds / SECONDS_PER_MONTH.to_f
end
🔎 See on GitHub
in_weeks()
Returns the amount of weeks a duration covers as a float
2.months.in_weeks # => 8.696
📝 Source code
# File activesupport/lib/active_support/duration.rb, line 379
def in_weeks
in_seconds / SECONDS_PER_WEEK.to_f
end
🔎 See on GitHub
in_years()
Returns the amount of years a duration covers as a float
30.days.in_years # => 0.082
📝 Source code
# File activesupport/lib/active_support/duration.rb, line 393
def in_years
in_seconds / SECONDS_PER_YEAR.to_f
end
🔎 See on GitHub
iso8601(precision: nil)
Build ISO 8601 Duration
string for this duration. The precision
parameter can be used to limit seconds' precision of duration.
📝 Source code
# File activesupport/lib/active_support/duration.rb, line 446
def iso8601(precision: nil)
ISO8601Serializer.new(self, precision: precision).serialize
end
🔎 See on GitHub
since(time = ::Time.current)
📝 Source code
# File activesupport/lib/active_support/duration.rb, line 409
def since(time = ::Time.current)
sum(1, time)
end
🔎 See on GitHub
to_i()
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.
📝 Source code
# File activesupport/lib/active_support/duration.rb, line 350
def to_i
@value.to_i
end
🔎 See on GitHub
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"
📝 Source code
# File activesupport/lib/active_support/duration.rb, line 326
def to_s
@value.to_s
end
🔎 See on GitHub