Skip to main content

Periods

The Periods category builds Period values — ISO-8601 durations like P5D or PT3H. A Period is one of TransformScript's runtime types (see Types and Coercion); it carries fields for years, months, weeks, days, hours, minutes, and seconds, and is written as a literal between pipes: |P1D|, |PT3H|, |P1Y2M3D|.

Periods exist to do temporal arithmetic. They add and subtract field-wise (|P1D| + |PT3H||P1DT3H|), and they apply to the temporal types from Dates & TimesDate, DateTime, and LocalDateTime — with + and -. The constructors below are a more readable way to produce a Period than writing the raw literal.

Each function is callable in prefix form fn(…) or postfix/UFCS form x fn(…). There is no pipe operator in TransformScript — the |…| pipes are temporal-literal delimiters only.

Because every Period renders with pipes (|P5D|), the examples on this page are shown in fenced code blocks rather than table cells — a literal | would break a Markdown table.

Single-Field Constructors

These six functions each take a single :number and build a Period with just that one field set. They differ only in which field they populate.

FunctionSignatureBuilds
years(:number)a years-only Period
months(:number)a months-only Period
days(:number)a days-only Period
hours(:number)an hours-only Period
minutes(:number)a minutes-only Period
seconds(:number)a seconds-only Period (accepts fractions)

The years, months, days, hours, and minutes constructors require an integer and raise if given a fractional number. Only seconds accepts a fraction.

years(1)      → |P1Y|
months(2)     → |P2M|
days(5)       → |P5D|
hours(3)      → |PT3H|
minutes(30)   → |PT30M|
seconds(90)   → |PT90S|
seconds(1.5)  → |PT1.5S|

Postfix (UFCS) form reads naturally:

5 days()      → |P5D|

Component Constructors

Two functions build a multi-field Period from an :object of named components. Keys are case-insensitive, and any omitted key defaults to 0.

period

Signature: period(:object)

Builds a calendar Period from years, months, and days keys. Time-of-day keys (hours, minutes, seconds) and weeks are not read by period — they are silently ignored. Use duration for time-based components.

period({ years: 1, months: 2, days: 3 })   → |P1Y2M3D|
period({ years: 1, weeks: 2 })             → |P1Y|

duration

Signature: duration(:object)

Builds a time Period from days, hours, minutes, and seconds keys. The seconds key accepts a fraction; the others must be integers. Calendar keys (years, months, weeks) are silently ignored — use period for those.

duration({ days: 1, hours: 2, minutes: 3, seconds: 4 })   → |P1DT2H3M4S|
duration({ seconds: 1.5 })                                → |PT1.5S|

between

Signature: between(:any, :any)

Computes the calendar Period between two dates, expressed in years, months, and days. The argument order is between(end, start) — the first argument is the later (end) date and the second is the earlier (start) date. Each argument is coerced to a date (a DateTime or LocalDateTime is reduced to its calendar date).

between(|2024-03-15|, |2024-01-10|)   → |P2M5D|
between(|2024-01-10|, |2024-01-10|)   → |P0D|

If the end date is earlier than the start date, the result fields are negative:

between(|2024-01-10|, |2024-03-15|)   → |P-2M-5D|

Because the receiver becomes the first argument under UFCS, postfix form reverses the intuitive reading — startDate between(endDate) treats the receiver as the end date, so prefer the prefix form for clarity.

Period Arithmetic

Periods combine with each other field-wise, and apply to temporal values with + and -:

days(1) + hours(3)                        → |P1DT3H|

|2024-05-01| + days(10)                   → |2024-05-11|
|2024-05-01| - period({ months: 2 })      → |2024-03-01|
|2024-01-31| + months(1)                  → |2024-02-29|

|2021-03-02T10:39:59| - |P1D|             → |2021-03-01T10:39:59|
|2021-03-02T10:39:59| + duration({ hours: 3 })  → |2021-03-02T13:39:59|

Applying a Period that has time-of-day components to a bare Date raises, since a Date has no time to advance:

|2024-05-01| + hours(3)
  → error: Cannot apply time-based period components to a Date literal