Date and time input
A date and a time of day typed or chosen together, read in one zone that the time states beside it, reported as an instant in UTC.
On this page
11 October 2026, 09:30 UTC
Code
import { DateTimeInput } from "@bosunkit/components/date-time-input";
import { useState, type Dispatch, type ReactElement, type SetStateAction } from "react";
export const description: string =
"A log entry's time in UTC, which cannot be after the current time, and a crew member's flight home in the " +
"device's own zone, printed with its offset. Each reports the instant in UTC.";
export default function Showcase(): ReactElement {
const [entry, setEntry]: [string, Dispatch<SetStateAction<string>>] = useState<string>("2026-10-11T09:30:00.000Z");
const [flight, setFlight]: [string, Dispatch<SetStateAction<string>>] = useState<string>("");
return (
<div style={{ width: "100%", display: "grid", gap: "var(--space-xl)" }}>
<DateTimeInput
label="Time of the entry"
now={Date.parse("2026-10-11T12:00:00.000Z")}
max="2026-10-11T12:00:00.000Z"
value={entry}
onValueChange={setEntry}
/>
<DateTimeInput
label="Flight home"
zone="local"
now={Date.parse("2026-10-11T12:00:00.000Z")}
value={flight}
onValueChange={setFlight}
/>
</div>
);
}
A date and time input holds an instant: a group named by its label, with the date picker
for the date and the time picker for the time of day, side by side where there is
room. Both read in one zone, which the time states beside it. By default that is UTC, as the log keeps times;
zone="local" makes it the device's own zone, printed as its offset from UTC at that instant (UTC+02:00), for a time
that belongs to a person ashore. The page always receives the instant as ISO 8601 in UTC. Under the group the
instant is written out with its reference: "11 October 2026, 09:30 UTC".
The instant is reported once both parts are set and it is within min and max, or both are cleared. The bounds
are instants: an entry that records what has happened takes the current time as max, and a later one is named with
the bound and its reference, "Choose a time up to 11 October 2026, 12:00 UTC.". The calendar disables the days
outside the bounds. Moving between the parts, or into their calendar and lists, is not leaving the group. A date
without a time or a time without a date is named once the crew leave it.
Examples
Empty
Code
import { DateTimeInput } from "@bosunkit/components/date-time-input";
import type { ReactElement } from "react";
export const description: string = "Empty: a date and a time to type or choose, the time with UTC beside it.";
export default function Empty(): ReactElement {
return <DateTimeInput label="Departure" now={Date.parse("2026-10-11T12:00:00.000Z")} />;
}
Not after now
11 October 2026, 11:40 UTC
Code
import { DateTimeInput } from "@bosunkit/components/date-time-input";
import type { ReactElement } from "react";
export const description: string =
"With `max` set to the current time, for an entry that records what has happened: a later instant is named with " +
"its reference and not reported.";
export default function Latest(): ReactElement {
return (
<DateTimeInput
label="Time of the entry"
now={Date.parse("2026-10-11T12:00:00.000Z")}
max="2026-10-11T12:00:00.000Z"
defaultValue="2026-10-11T11:40:00.000Z"
/>
);
}
The device's zone
Code
import { DateTimeInput } from "@bosunkit/components/date-time-input";
import type { ReactElement } from "react";
export const description: string =
'`zone="local"` reads and writes the device\'s own time and prints its offset from UTC beside it, for a time that ' +
"belongs to a person ashore.";
export default function LocalZone(): ReactElement {
return <DateTimeInput label="Taxi to the airport" zone="local" now={Date.parse("2026-10-11T12:00:00.000Z")} />;
}
Invalid
Code
import { DateTimeInput } from "@bosunkit/components/date-time-input";
import type { ReactElement } from "react";
export const description: string =
"A date without a time, a time without a date, or an instant past the bounds is named under the group once the " +
"crew leave it.";
export default function Invalid(): ReactElement {
return (
<DateTimeInput
label="Departure"
now={Date.parse("2026-10-11T12:00:00.000Z")}
defaultValue="2026-10-14T06:15:00.000Z"
error="Choose a time from 15 October 2026, 00:00 UTC on."
/>
);
}
Read-only
10 October 2026, 17:20 UTC
Code
import { DateTimeInput } from "@bosunkit/components/date-time-input";
import type { ReactElement } from "react";
export const description: string = "Read-only: the instant shown in its parts, with dashed outlines.";
export default function ReadOnly(): ReactElement {
return (
<DateTimeInput
label="Anchored"
readOnly
now={Date.parse("2026-10-11T12:00:00.000Z")}
defaultValue="2026-10-10T17:20:00.000Z"
/>
);
}
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| labelrequired | string | – | The group's name, translated by the caller: "Departure", "Time of the entry". |
| value | string | undefined | – | The instant as ISO 8601 in UTC (2026-10-11T14:30:00.000Z); "" for none. |
| defaultValue | string | undefined | – | The instant it starts with when the caller does not hold value. |
| onValueChange | ((iso: string) => void) | undefined | – | Called with the instant, ISO 8601 in UTC, when both its date and time are set and within the bounds; "" when
both are cleared. |
| min | string | undefined | – | The earliest instant that can be chosen (ISO 8601). |
| max | string | undefined | – | The latest instant that can be chosen (ISO 8601): the current time for an entry that records what happened. |
| zone | ClockZone | undefined | "utc" | The clock the date and time are read and written in: utc by default, as the log keeps them; local for the
device's time zone, whose offset is printed. |
| now | number | undefined | – | The current instant in epoch milliseconds, in place of the clock's, for Today and Now. |
| hint | string | undefined | – | Text under the group, translated by the caller; the instant written out with its reference when unset. |
| error | string | undefined | – | The caller's own error, shown under the group. |
| required | boolean | undefined | – | Whether the group must hold an instant. |
| disabled | boolean | undefined | – | Whether the group takes no input. |
| readOnly | boolean | undefined | – | Whether the group shows its instant without letting the crew change it. |
| name | string | undefined | – | The form field name; the form receives the instant, ISO 8601 in UTC. |
| className | string | undefined | – | Classes added to the group's own. |
| testId | string | undefined | – | data-testid on the group. |
Related
- Date picker: a date on its own.
- Time picker: a time of day on its own.
- Date range picker: a range of whole days.