Fuzion Logo
fuzion-lang.dev — The Fuzion Language Portal
JavaScript seems to be disabled. Functionality is limited.

time/duration.fz


# This file is part of the Fuzion language implementation.
#
# The Fuzion language implementation is free software: you can redistribute it
# and/or modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation, version 3 of the License.
#
# The Fuzion language implementation is distributed in the hope that it will be
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
# License for more details.
#
# You should have received a copy of the GNU General Public License along with The
# Fuzion language implementation.  If not, see <https://www.gnu.org/licenses/>.


# -----------------------------------------------------------------------
#
#  Tokiwa Software GmbH, Germany
#
#  Source code of Fuzion standard library feature time.duration
#
#  Author: Fridtjof Siebert (siebert@tokiwa.software)
#
# -----------------------------------------------------------------------

# time.duration -- value representing a duration, i.e., a time span
#
# This is intended for high precision time specification and measurement, it
# uses a time resolution of 1ns.
#
# The maximum value is about 580 years, so this is not intended for use in
# calendars that may require time spans exceeding several centuries or millennia,
# nor astrological time spans.
#
module:public duration (

  # the duration in nano seconds
  #
  public nanos u64
  )
  : Period,
    property.orderable,
    property.hashable

is

  # For `duration`, this feature redefined from `Period` will just return an equal `duration`
  # like `duration.this`.
  #
  public redef fixed as_duration time.duration
  =>
    # NYI: UNDER DEVELOPMENT: #5595: Once `time` is declared `final` or similar, this should work:
    #
    #   duration.this
    time.duration nanos


  # is this period infinite, i.e., it never ends?
  #
  public redef is_infinity bool
  =>
    false


  # this duration in micro seconds, omitting fractional part
  #
  public micros u64 => nanos / time_unit.?s.in_ns

  # this duration in milli seconds, omitting fractional part
  #
  public millis u64 => nanos / time_unit.ms.in_ns

  # this duration in whole seconds, omitting fractional part
  #
  public seconds u64 => nanos / time_unit.s.in_ns

  # this duration in whole minutes, omitting fractional part
  #
  public minutes u64 => nanos / time_unit.m.in_ns

  # this duration in whole hours, omitting fractional part
  #
  public hours u64 => nanos / time_unit.h.in_ns

  # this duration in whole days, omitting fractional part
  #
  public days u64 => nanos / time_unit.d.in_ns

  # this duration in whole weeks, omitting fractional part
  #
  public weeks u64 => nanos / time_unit.w.in_ns

  # this duration in whole Julian years, omitting fractional part
  #
  public years u64 => nanos / time_unit.a.in_ns


  # this duration and another one combined
  #
  public infix + (other duration) duration
  pre
    safety: nanos +! other.nanos
  =>
    duration (nanos + other.nanos)


  # this duration minus another duration
  #
  public fixed infix - (other duration) duration
  pre
    safety: duration.this >= other
  =>
    duration (nanos - other.nanos)


  # this duration multiplied by factor n
  #
  public redef infix * (n u64) time.duration
  =>
    time.duration nanos*n


  # this duration multiplied by factor f
  #
  public times(f f64) time.duration
  =>
    time.duration (nanos.as_f64 * f).as_i64.as_u64


  # this duration divided by duration other, rounding down
  #
  public infix / (other duration.this) u64
  =>
    nanos / other.nanos


  # create a string representation of this duration. The string
  # representation is not accurate, it consists of at least two
  # and at most 4 decimal digits followed by a time unit string.
  #
  public redef as_string String =>
    as_string unit_for_as_string false


  # create a string representation of this duration. The string
  # representation is not accurate, it consists of at least two
  # and at most 4 decimal digits followed by a time unit string.
  # Output is padded for nice alignment in e.g. a table.
  #
  public as_string_pad String =>
    as_string unit_for_as_string true


  # create a string representation of this duration. The string
  # representation is not accurate, it consists of at least two
  # and at most 4 decimal digits followed by a time unit string.
  #
  public as_string_long String =>
    as_string_long unit_for_as_string


  # create a string representation of this duration using the given unit.
  #
  public as_string(u time.time_unit) String =>
    as_string u false

  # create a string representation of this duration using the given unit.
  #
  as_string(u time.time_unit, pad bool) String =>
    n := $(nanos / u.in_ns)
    "{pad ? n.pad_left 4 : n}{u.short_name}"


  # create a string representation of this duration using the given unit
  # use the long version of the unit (e.g. 'hours' instead of 'h')
  #
  public as_string_long(u time.time_unit) String =>
    "{nanos / u.in_ns} {u.name}"


  # create a string representation of this duration. The string
  # representation is not accurate, it consists of at least two
  # and at most 4 decimal digits followed by a time unit string.
  #
  public unit_for_as_string time.time_unit =>
    for
      x := time.time_unit.ns, nx.or_panic
      nx := x.larger
    while nx >>? (u -> nanos / u.in_ns >= 10) else
      x


  # total order
  #
  public fixed redef type.lteq(a, b time.duration) bool =>
    u64.type.lteq a.nanos b.nanos


  # create hash code from a duration
  #
  public redef type.hash_code(d duration.this) u64 =>
    d.nanos


  # max value for a duration given in nanoseconds
  public type.max_duration_nanos   u64 => u64.max

  # max value for a duration given in microseconds
  public type.max_duration_micros  u64 => u64.max / time.time_unit.?s.in_ns

  # max value for a duration given in milliseconds
  public type.max_duration_millis  u64 => u64.max / time.time_unit.ms.in_ns

  # max value for a duration given in seconds
  public type.max_duration_seconds u64 => u64.max / time.time_unit.s.in_ns

  # max value for a duration given in minutes
  public type.max_duration_minutes u64 => u64.max / time.time_unit.m.in_ns

  # max value for a duration given in hours
  public type.max_duration_hours   u64 => u64.max / time.time_unit.h.in_ns

  # max value for a duration given in days
  public type.max_duration_days    u64 => u64.max / time.time_unit.d.in_ns

  # max value for a duration given in weeks
  public type.max_duration_weeks   u64 => u64.max / time.time_unit.w.in_ns

  # max value for a duration given in years
  public type.max_duration_years   u64 => u64.max / time.time_unit.a.in_ns


  # create duration of n ns
  #
  # NYI: Turn this into a 'postfix' call, see https://fuzion-lang.dev/design/postfix_calls
  #
  public type.ns (n u64) time.duration
  pre
    debug: n ? max_duration_nanos
  => time.duration n


  # create duration of n ?s
  #
  # NYI: Turn this into a 'postfix' call, see https://fuzion-lang.dev/design/postfix_calls
  #
  public type.?s (n u64) time.duration
  pre
    debug: n ? max_duration_micros
  => time.duration n*time_unit.?s.in_ns


  # create duration of n ms
  #
  # NYI: Turn this into a 'postfix' call, see https://fuzion-lang.dev/design/postfix_calls
  #
  public type.ms (n u64) time.duration
  pre
    debug: n ? max_duration_millis
  => time.duration n*time_unit.ms.in_ns


  # create duration of n seconds
  #
  # NYI: Turn this into a 'postfix' call, see https://fuzion-lang.dev/design/postfix_calls
  #
  public type.s (n u64) time.duration
  pre
    debug: n ? max_duration_seconds
  => time.duration n*time_unit.s.in_ns


  # create duration of n seconds
  #
  # NYI: Turn this into a 'postfix' call, see https://fuzion-lang.dev/design/postfix_calls
  #
  public type.seconds (n u64) time.duration
  pre
    debug: n ? max_duration_seconds
  => s n


  # create duration of n min
  #
  # NYI: Turn this into a 'postfix' call, see https://fuzion-lang.dev/design/postfix_calls
  #
  public type.min (n u64) time.duration
  pre
    debug: n ? max_duration_minutes
  => time.duration n*time_unit.m.in_ns


  # create duration of n min
  #
  # NYI: Turn this into a 'postfix' call, see https://fuzion-lang.dev/design/postfix_calls
  #
  public type.minutes (n u64) time.duration
  pre
    debug: n ? max_duration_minutes
  => min n


  # create duration of n hours
  #
  # NYI: Turn this into a 'postfix' call, see https://fuzion-lang.dev/design/postfix_calls
  #
  public type.h (n u64) time.duration
  pre
    debug: n ? max_duration_hours
  => time.duration n*time.time_unit.h.in_ns


  # create duration of n hours
  #
  # NYI: Turn this into a 'postfix' call, see https://fuzion-lang.dev/design/postfix_calls
  #
  public type.hours (n u64) time.duration
  pre
    debug: n ? max_duration_hours
  => h n


  # create duration of n days
  #
  # NYI: Turn this into a 'postfix' call, see https://fuzion-lang.dev/design/postfix_calls
  #
  public type.days  (n u64) time.duration
  pre
    debug: n ? max_duration_days
  => time.duration n*time.time_unit.d.in_ns


  # create duration of n weeks
  #
  # NYI: Turn this into a 'postfix' call, see https://fuzion-lang.dev/design/postfix_calls
  #
  public type.weeks (n u64) time.duration
  pre
    debug: n ? max_duration_weeks
  => time.duration n*time.time_unit.w.in_ns


  # create duration of n years
  #
  # NYI: Turn this into a 'postfix' call, see https://fuzion-lang.dev/design/postfix_calls
  #
  public type.a (n u64) time.duration
  pre
    debug: n ? max_duration_years
  => time.duration n*time.time_unit.a.in_ns


  # create duration of n years
  #
  # NYI: Turn this into a 'postfix' call, see https://fuzion-lang.dev/design/postfix_calls
  #
  public type.years (n u64) time.duration
  pre
    debug: n ? max_duration_years
  => a n


  # the zero duration, representing a time span of zero
  #
  public type.zero time.duration => time.duration 0


  # the maximum duration
  #
  public type.max time.duration => time.duration.ns time.duration.max_duration_nanos

last changed: 2026-04-21