Class: Horologium::Duration

Inherits:
Object
  • Object
show all
Includes:
PreciseValue
Defined in:
lib/horologium/duration.rb,
sig/horologium/duration.rbs

Overview

An amount of time in SI seconds, with no date and no scale attached. Duration.days(1) is always 86,400 SI seconds. Because of leap seconds a civil day can be a second longer or shorter, so a Duration and a calendar day are different things.

A Duration is frozen. Its precision is set when it is built, from the precision in effect unless you pass one. At :standard it holds the seconds as a Numeric::TwoPartFloat, at :exact as a Numeric::Exact.

Two durations add and subtract to give another duration, and one negates. Mixing a :standard and an :exact operand gives an :exact result. Adding an Instant to a Duration raises DimensionalError; it is Instant#+ that shifts a point by a span.

Examples:

A day is a fixed number of SI seconds

Horologium::Duration.days(1) == Horologium::Duration.seconds(86_400)
# => true

Constant Summary collapse

SECONDS_PER_DAY =

The number of SI seconds in a day.

Returns:

  • (Integer)
86_400
NANOSECONDS_PER_SECOND =

The number of nanoseconds in a second.

Returns:

  • (Integer)
1_000_000_000

Instance Attribute Summary

Attributes included from PreciseValue

#precision, #rational, #value

Class Method Summary collapse

Instance Method Summary collapse

Methods included from PreciseValue

#<=>, #eql?, #hash, #initialize

Class Method Details

.days(count, precision: Horologium.current_precision) ⇒ Horologium::Duration

A duration of count days, each of SECONDS_PER_DAY SI seconds. This counts time and is not tied to the calendar.

Examples:

Horologium::Duration.days(1) == Horologium::Duration.seconds(86_400)
# => true

Parameters:

  • count (Numeric)

    the number of days

  • precision (Symbol) (defaults to: Horologium.current_precision)

    :standard or :exact, taken from the precision in effect when omitted

  • precision: (Symbol) (defaults to: Horologium.current_precision)

Returns:



53
54
55
# File 'lib/horologium/duration.rb', line 53

def days(count, precision: Horologium.current_precision)
  from_seconds(count * SECONDS_PER_DAY, precision)
end

.nanoseconds(count, precision: Horologium.current_precision) ⇒ Horologium::Duration

A duration of count nanoseconds.

Examples:

Horologium::Duration.nanoseconds(1)

Parameters:

  • count (Numeric)

    the number of nanoseconds

  • precision (Symbol) (defaults to: Horologium.current_precision)

    :standard or :exact, taken from the precision in effect when omitted

  • precision: (Symbol) (defaults to: Horologium.current_precision)

Returns:



65
66
67
# File 'lib/horologium/duration.rb', line 65

def nanoseconds(count, precision: Horologium.current_precision)
  from_seconds(Rational(count) / NANOSECONDS_PER_SECOND, precision)
end

.seconds(count, precision: Horologium.current_precision) ⇒ Horologium::Duration

A duration of count SI seconds.

Examples:

Horologium::Duration.seconds(3600)

Parameters:

  • count (Numeric)

    the number of seconds

  • precision (Symbol) (defaults to: Horologium.current_precision)

    :standard or :exact, taken from the precision in effect when omitted

  • precision: (Symbol) (defaults to: Horologium.current_precision)

Returns:



39
40
41
# File 'lib/horologium/duration.rb', line 39

def seconds(count, precision: Horologium.current_precision)
  from_seconds(count, precision)
end

Instance Method Details

#+(other) ⇒ Horologium::Duration

Parameters:

Returns:

Raises:



86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/horologium/duration.rb', line 86

def +(other)
  unless other.is_a?(Duration)
    raise DimensionalError,
      "cannot add a #{other.class} to a Duration; " \
      "only a Duration combines with a Duration"
  end

  precision = Numeric::Precision.resolve(self.precision, other.precision)

  self.class.new(
    Numeric::Precision.add(value, other.value),
    precision
  )
end

#-(other) ⇒ Horologium::Duration

Negative when the other is the longer of the two.

Parameters:

Returns:

Raises:



106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/horologium/duration.rb', line 106

def -(other)
  unless other.is_a?(Duration)
    raise DimensionalError,
      "cannot subtract a #{other.class} from a Duration; " \
      "only a Duration combines with a Duration"
  end

  precision = Numeric::Precision.resolve(self.precision, other.precision)

  self.class.new(
    Numeric::Precision.subtract(value, other.value),
    precision
  )
end

#-@Horologium::Duration

The same length, the other way round.



124
125
126
# File 'lib/horologium/duration.rb', line 124

def -@
  self.class.new(value * -1, precision)
end

#absHorologium::Duration

The same length, never negative.



131
132
133
# File 'lib/horologium/duration.rb', line 131

def abs
  negative? ? -self : self
end

#inspectString

Returns:

  • (String)


166
167
168
# File 'lib/horologium/duration.rb', line 166

def inspect
  format("#<%s %s s (%s)>", self.class, to_f, precision)
end

#negative?Boolean

Returns:

  • (Boolean)


141
142
143
# File 'lib/horologium/duration.rb', line 141

def negative?
  rational.negative?
end

#positive?Boolean

Returns:

  • (Boolean)


146
147
148
# File 'lib/horologium/duration.rb', line 146

def positive?
  rational.positive?
end

#to_fFloat

The duration in SI seconds. A Float has about 15 digits, so a long duration loses its small end here; use #to_r for the whole of it.

Returns:

  • (Float)


161
162
163
# File 'lib/horologium/duration.rb', line 161

def to_f
  value.to_f
end

#to_rRational

The duration in SI seconds, exactly.

Returns:

  • (Rational)


153
154
155
# File 'lib/horologium/duration.rb', line 153

def to_r
  rational
end

#zero?Boolean

Returns:

  • (Boolean)


136
137
138
# File 'lib/horologium/duration.rb', line 136

def zero?
  rational.zero?
end