Skip to main content

Coercions

The Coercions category holds functions that convert a value from one type to another: toString, toNumber, toDecimal, toBoolean, and the temporal four toDate, toDateTime, toLocalDateTime, and toTime. Each is callable in prefix form fn(x, …) or postfix/UFCS form x fn(…).

These toX functions are a different mechanism from the as Type cast. They overlap in spirit but deliberately diverge in their edge cases: toString(null) is "" while null as String stays null, toNumber always yields a decimal while as Number preserves integers, and toBoolean never raises while as Boolean does. See Types and Coercion for the full picture of all four coercion mechanisms (truthiness, as Type, these toX functions, and operator coercion), and the toX vs as Type callout below for the specifics.

Scalar Coercions

These four convert to String, Number, Boolean. Cells use for results.

FunctionSignatureDescriptionExample
toString(:any)Stringifies the value. null becomes the empty string. Arrays and objects use native rendering, not JSON.toString(42.5)"42.5"; toString(null)""
toNumber(:any)Parses to a decimal Number (always, even for whole values). Accepts numeric strings, numbers, and booleans (true1.0, false0.0). Raises on non-numeric strings and on null. No grouping separators.toNumber("42")42.0; toNumber(true)1.0
toDecimal(:any)Parses to an exact decimal Number from a Number or numeric string. Raises on booleans, null, and non-numeric strings.toDecimal("3.14")3.14; toDecimal(42)42
toBoolean(:any)Converts to a Boolean and never raises. Recognizes (trimmed, case-insensitive) true/1/yestrue and false/0/nofalse; any other value falls back to truthiness, where only false and null are falsy.toBoolean("yes")true; toBoolean(0)false; toBoolean("maybe")true

A few details to keep in mind:

  • toNumber returns a Number whose value is always a float — toNumber("42") is 42.0, never the integer 42. toDecimal returns a Number too, but does not force a fractional form (toDecimal(42)42).
  • toBoolean falls back to plain truthiness, so toBoolean("maybe"), toBoolean(""), and toBoolean(5) are all true; only the recognized false-words, false, null, and 0/0.0 are false.
  • toString on a Number, Boolean, Array, or Object uses native rendering (e.g. toString([1, 2, 3])"[1, 2, 3]"). It is not JSON encoding — for JSON output use as String on a collection or a dedicated serializer.

Temporal Coercions

The four temporal coercions accept temporal literals (written with |…|), other temporal values, and strings. Because the |…| literal uses the pipe character, the examples below are shown in fenced code blocks rather than table cells.

Two of them take an optional strptime format string as the second argument; the other two take an optional time zone. They are not interchangeable.

toDate(:any, :string?) — Second Arg Is a strptime Format

Returns a Date (calendar date, no time). Accepts a Date, a DateTime, a LocalDateTime, or a string. With a second argument, the string is parsed with that strptime format.

toDate("2024-05-01")              →  |2024-05-01|
toDate(|2024-05-01T23:57:59-07:00|)  →  |2024-05-01|
toDate("05/01/2024", "%m/%d/%Y")  →  |2024-05-01|

toTime(:any, :string?) — Second Arg Is a strptime Format

Despite the name, toTime returns a DateTime (a full zoned instant), not a bare time-of-day. Without a format it requires a value that parses as a Time; a bare time string or a LocalTime literal is not accepted, so in practice supply a strptime format. With a format, the missing date defaults to today.

toTime("11:30 PM", "%I:%M %p")    →  a DateTime at 23:30:00 on today's date
toTime("23:57:59")                →  raises (cannot parse a bare time without a zone context)
toTime(|23:57:59|)                →  raises (a LocalTime value is not accepted)

toDateTime(:any, :string?) — Second Arg Is a Time Zone

Returns a DateTime (zoned instant). Accepts a temporal value or an ISO-8601 string. The optional second argument is a time zone name; when given, the result is shifted into that zone.

toDateTime("2024-05-01T12:00:00Z")                       →  |2024-05-01T12:00:00Z|
toDateTime(|2020-10-01T23:57:59-07:00|)                  →  |2020-10-01T23:57:59-07:00|
toDateTime("2024-05-01T12:00:00Z", "America/New_York")   →  |2024-05-01T08:00:00-04:00|

toLocalDateTime(:any, :string?) — Second Arg Is a Time Zone

Returns a LocalDateTime (date + time, no zone). Accepts a temporal value or string. A LocalDateTime passes through unchanged when no zone is given. The optional second argument is a time zone: the instant is first shifted into that zone, then the zone is dropped, so the wall-clock fields reflect that zone.

toLocalDateTime(|2020-10-01T23:57:59-07:00|)            →  |2020-10-01T23:57:59|
toLocalDateTime("2024-05-01T12:00:00Z")                 →  |2024-05-01T12:00:00|
toLocalDateTime("2024-05-01T12:00:00Z", "Europe/Paris") →  |2024-05-01T14:00:00|

toX vs as Type

The toX functions and the as Type cast are separate mechanisms:

InputtoX resultas Type result
null to StringtoString(null)""null as Stringnull
"42" to NumbertoNumber("42")42.0 (decimal)"42" as Number42 (integer preserved)
"maybe" to BooleantoBoolean("maybe")true (truthiness fallback)"maybe" as Booleanraises Unable to interpret 'maybe' as Boolean
"yes" to BooleantoBoolean("yes")true"yes" as Booleantrue

Rules of thumb:

  • toString is total; as String preserves null. Reach for toString when you want a guaranteed string (empty for null); use as String when null must stay null, or when you need formatting options (format, timeZone) or JSON-encoded collections.
  • toNumber always returns a decimal; as Number preserves integers and supports locale/separator options. Use toDecimal for an exact decimal that does not force a fractional form. Neither toNumber nor toDecimal accepts grouping separators (toNumber("1,000") raises); as Number with groupingSeparator does.
  • toBoolean never raises; as Boolean does. toBoolean recognizes 1/yes/0/no and otherwise falls back to truthiness. as Boolean accepts a fixed vocabulary and raises on anything outside it (customizable with trueValues/falseValues).
  • Argument shapes differ across temporal coercions. toDate and toTime take an optional strptime format; toDateTime and toLocalDateTime take an optional time zone. (toTime returns a DateTime, not a LocalTime.)