Type Formats
Date and Time Formats
Date strings, native Dates and Temporal values, with fixed or relative bounds.
Date Representations
A date comes in three shapes, each with its own format family. All three take the same min / max / gt / lt bounds, written in the type's own ISO form: a PlainDate takes '2020-01-01', an Instant takes '2020-01-01T00:00:00Z'.
- String-encoded:
TF.StringDate,TF.StringTime,TF.StringDateTimecheck an ISO string in a fixed layout ('2020-01-01','08:30'). - Native
Date:TF.Datechecks a real JSDate;TF.DateFuture/TF.DatePastare ready-made (aDatethat's>= now/<= now). - TC39 Temporal:
TFT.PlainDate,TFT.ZonedDateTime,TFT.Instant,TFT.PlainTime,TFT.PlainDateTime,TFT.PlainYearMonthcheck an actualTemporal.*instance. Import them from@mionjs/run-types/formats/temporal(asTFT), so apps that don't use Temporal never pull in its lib.
import type * as TF from '@mionjs/run-types/formats';
import type * as TFT from '@mionjs/run-types/formats/temporal';
// The same "2020 or later" bound, two representations:
type DateString = TF.StringDate<{min: '2020-01-01'}>; // an ISO string
type PlainDate = TFT.PlainDate<{min: '2020-01-01'}>; // a Temporal.PlainDate
Temporal values are checked with
instanceof, not by shape. Temporal.PlainMonthDay and Temporal.Duration have no min/max ordering, so they take no bounds. DataOnly<Temporal.PlainDate> stays a Temporal.PlainDate.Date Format Builders
With builders, use TF.date(...) and the TFT.* temporal namespace.
import * as TF from '@mionjs/run-types/formats';
import * as TFT from '@mionjs/run-types/formats/temporal';
TF.date({max: 'now'}); // a Date in the past
TFT.plainDate({min: '2020-01-01'}); // a Temporal.PlainDate, 2020 on
TFT.instant({min: 'now-PT1H'}); // an Instant within the last hour
Relative Date Bounds
Write a bound as now, or now plus or minus an ISO-8601 duration such as P1Y2M10D (1 year, 2 months, 10 days), P1W (1 week) or PT12H30M (12 hours, 30 minutes). The build checks that the units fit the field.
import type * as TF from '@mionjs/run-types/formats';
import {createValidateFn} from '@mionjs/run-types';
// `now` is the current time each time a value is validated
// A birth date in the past, no more than 120 years ago.
type BirthDate = TF.StringDate<{min: 'now-P120Y'; max: 'now'}>;
// A meeting that starts within the next 30 days.
type StartsSoon = TF.StringDateTime<{min: 'now'; max: 'now+P30D'}>;
const isBirthDate = createValidateFn<BirthDate>();
const startsSoon = createValidateFn<StartsSoon>();
isBirthDate('1990-05-20'); // true
isBirthDate('1850-01-01'); // false, more than 120 years ago
export {isBirthDate, startsSoon};
| Family | Relative units |
|---|---|
Date-only (TF.stringDate, TFT.plainDate, TFT.plainYearMonth) | date: Y M W D |
Time-only (TF.stringTime, TFT.plainTime, TFT.instant) | time: H M S |
Date + time (TF.stringDateTime, native TF.date, TFT.plainDateTime, TFT.zonedDateTime) | both |
min / max are inclusive, gt / lt exclusive. Use one or the other per edge, as on a number format.