kex docs Standard Library 0.4.0-alpha kex.run ↗

Unitsprelude

trait Unit

Numbers that carry a unit.

Writing 5.sec or 90.minute gives you a Measure: a number, the unit it was written in, and the same quantity in that dimension's base unit. Adding, subtracting and converting all go through the canonical value, so the arithmetic is right regardless of which units the operands were written in, and mixing dimensions is an Error rather than a silently wrong number.

5.sec.to(String)                     # => "5.0 s"
1.5.hour.to(String)                  # => "1.5 h"
(1.hour ` 30.minute).map(~to(String))  # => Ok("1.5 h")
90.minute.convert(Hour)              # => Ok(1.5 h)

The time units (nanosecond through week) are in the prelude. Other dimensions live in opt-in modules under Units, and every one of them measures against the same machinery here.

A `Measure` is a measurement, not an elapsed span: `5.sec` describes a quantity, while `Duration` is what `Time` and `Date+ use for a span between two moments.

The trait a unit implements: how it converts to its dimension's base unit, which dimension that is, and how it is written.

factor

How many base units one of this unit is: 60.0 for a minute, whose base unit is the second.

factor : Float

Returns: Float — the conversion factor

Examples
Minute.factor   # => 60.0

kind

Which dimension this unit measures, as an atom. Only measures of the same kind can be added or converted between.

kind : Atom

Returns: Atom — the dimension tag

Examples
Second.kind   # => :time

symbol

How this unit is written when a measure is displayed.

symbol : String

Returns: String — the unit's symbol

Examples
Minute.symbol   # => "min"

function measureKind

The dimension a measure belongs to.

measureKind(measure)
Parameters
measure Measure
the measure to inspect

Returns: Atom — the dimension tag

Examples
measureKind(5.sec)   # => :time

function measureSymbol

The symbol a measure displays with.

measureSymbol(measure)
Parameters
measure Measure
the measure to inspect

Returns: String — the unit's symbol

Examples
measureSymbol(5.minute)   # => "min"

function measureFactor

The conversion factor of a measure's unit.

measureFactor(measure)
Parameters
measure Measure
the measure to inspect

Returns: Float — the conversion factor

Examples
measureFactor(5.minute)   # => 60.0

record UnitDefinition

A unit described at run time rather than by a constructor.

Runtime-defined units are used for prefixes and units derived by arithmetic: s^2 from squaring a duration, a kilo- prefix applied to a base unit.

Fields

conversionFactor
Float
dimension
Atom
notation
String

make UnitDefinition implements Unit

record Measure

A quantity with a unit.

A Measure is shared by every unit module. canonical stores the value in that dimension's base unit; its Unit controls its display. That split is what makes 1.hour 30.minute+ correct and still print in hours.

Fields

canonical
Float
value
Float
unit
UnitDefinition

record Duration

An elapsed span of time, in seconds.

Duration is an elapsed span used by Time, Date, and DateTime. A time Measure is deliberately not a Duration: 5.sec describes a measurement.

Fields

seconds
Float

type TimeUnit

The time units, from nanoseconds to weeks. The base unit is the second.

Variants

  • Nanosecond
  • Microsecond
  • Millisecond
  • Second
  • Minute
  • Hour
  • Day
  • Week

make TimeUnit implements Unit

factor

factor(@Nanosecond)

symbol

symbol(@Nanosecond)

make Integer

Time-unit constructors on Integer: 5.sec, 90.minute, 2.week.

Each answers a Measure whose display unit is the one you named, so 90.minute prints as minutes even though it is stored as 5400 seconds.

timeMeasure

timeMeasure(unit)

make Float

The same time-unit constructors on Float, for fractional quantities: 1.5.hour, 0.25.sec.

timeMeasure

timeMeasure(unit)

make Measure

to

to(String)

scale

Formatting into a target display unit deliberately has NO prelude clause. A unit module (Units.SI, Units.Data, ...) supplies to(String, in:) for the units it owns, and reaching one requires importing it. A catch-all here would answer None for an un-imported module instead: a silently empty Optional in place of "you need using Units.SI".

Multiplies the measure by a plain number, keeping its unit.

The unit is unchanged, so this scales a quantity rather than converting it: three of a two-second interval is six seconds.

scale(multiplier)
Parameters
multiplier Number
the factor to multiply by

Returns: Measure — the scaled measure

Examples
2.sec.scale(3).to(String)     # => "6.0 s"
1.hour.scale(0.5).to(String)  # => "0.5 h"

^

Raises the measure to a power, recording the derived unit in its notation.

Raising a measure preserves its display unit while applying the power to its canonical value, display value, and conversion factor. The current Unit trait represents a dimension as one Atom, so the dimension remains the base kind; the notation records the derived unit (for example s^2).

^(exponent)
Parameters
exponent Number
the power to raise to

Returns: Measure — the raised measure

Examples
(2.sec ^ 2).to(String)   # => "4.0 s^2"

convertTo

Converts the measure to another unit of the same dimension.

Answers Error when the dimensions differ: you cannot express seconds in bytes, and this says so rather than producing a wrong number.

Convert through the Unit trait so units from opt-in modules (SI, Data, and future domains) remain interchangeable with prelude time units.

convertTo(unit)
Parameters
unit Unit
the unit to convert to

Returns: Result<Measure, String> — the converted measure, or why it could not be

Examples
1.day.convertTo(Hour).map { |m| m.to(String) }     # => Ok("24.0 h")
90.minute.convertTo(Hour).map { |m| m.to(String) } # => Ok("1.5 h")

convert

Converts the measure to another time unit. The short spelling of convertTo, kept for prelude time measures.

convert(unit)
Parameters
unit TimeUnit
the time unit to convert to

Returns: Result<Measure, String> — the converted measure, or why it could not be

Examples
90.minute.convert(Hour).map { |m| m.to(String) }   # => Ok("1.5 h")

+

Adds two measures of the same dimension.

The units need not match: the sum goes through the canonical values, and comes back displayed in the LEFT operand's unit. Adding measures of different dimensions is an Error.

+(other)
Parameters
other Measure
the measure to add

Returns: Result<Measure, String> — the sum, or why they could not be added

Examples
(1.hour ` 30.minute).map { |m| m.to(String) }   # => Ok("1.5 h")
(30.minute ` 1.hour).map { |m| m.to(String) }   # => Ok("90.0 min")

-

Subtracts a measure of the same dimension.

Like , the result is displayed in the left operand's unit, and mixing dimensions is an Error+.

-(other)
Parameters
other Measure
the measure to subtract

Returns: Result<Measure, String> — the difference, or why they could not be subtracted

Examples
(1.hour - 30.minute).map { |m| m.to(String) }   # => Ok("0.5 h")

module Units

The time units are prelude-global, because every unit module measures against the same dimensions: Units.SI defines Watt * Hour with the Hour declared above, and future domains do the same. That makes Hour correct but not obviously located, so the same constructors are reachable under Units too, for call sites that would rather name where a unit comes from. These are aliases, not copies: each binds the identical constructor, so Units.Hour and Hour match the same patterns and compare equal.

constant Nanosecond ?

constant Microsecond ?

constant Millisecond ?

constant Second ?

constant Minute ?

constant Hour ?

constant Day ?

constant Week ?

Submodules

  • Units.Data Data sizes: bytes, kilobytes, and their binary counterparts.
  • Units.SI SI units: metres, grams, watts, volts and the rest, with prefixes and dimensional arithmetic.