ISO 8601 UTC strings
Every Kalyx value — value, defaultValue, onChange's argument, every item in a DateRange — is an ISO 8601 UTC string or null. Never a Date object.
type ISODateString = string; // e.g. "2026-04-15T00:00:00.000Z"
Why not Date?
Date objects are mutable, timezone-ambiguous, and serialize inconsistently. The classic bug:
// User in Seoul picks April 15
const picked = new Date(2026, 3, 15); // "2026-04-14T15:00:00.000Z" in KST 🤦
// Save to DB
await save(picked);
// Read back from DB in a UTC server
new Date(picked.toISOString()).getDate(); // 14 — off by one
ISO strings eliminate the ambiguity at the boundary:
<DatePicker
value="2026-04-15T00:00:00.000Z" // always UTC midnight
onChange={(iso) => save(iso)} // always a UTC string
/>
Kalyx guarantees:
- Dates are stored as UTC midnight (
T00:00:00.000Z) unless a time is explicitly set. onChangenever fires with aDate— only a string ornull.- Internal arithmetic uses the
DateAdapterwhich is UTC-safe end to end.
Displaying in local time
The value is UTC. Display is a rendering concern — handled by displayFormat and locale on each root:
<DatePicker
value={iso}
onChange={setIso}
displayFormat="MMM d, yyyy"
locale="en-US"
/>
Under the hood, the adapter formats the UTC instant using the requested locale.
Converting to and from Date
When you must bridge to a Date — for example, in a legacy form library — do it at the edge:
// Date → ISO
const iso = new Date(2026, 3, 15).toISOString();
// → "2026-04-14T15:00:00.000Z" (still KST-affected!)
// Safer: construct a UTC midnight directly
const iso = new Date(Date.UTC(2026, 3, 15)).toISOString();
// → "2026-04-15T00:00:00.000Z"
// ISO → Date
const date = new Date(iso);
For fine-grained conversion Kalyx exports helpers from @kalyx/core:
import { normalizeISO, parseInputValue, DateFnsAdapter } from '@kalyx/react';
normalizeISO('2026-04-15'); // "2026-04-15T00:00:00.000Z"
parseInputValue('15/04/2026', 'dd/MM/yyyy', DateFnsAdapter); // → ISO or null
Times and time zones
TimePicker and DateTimePicker also return ISO strings. The date part of a pure TimePicker value is a stable placeholder — consume only the time fields (getTime(iso) in @kalyx/core helps).
For IANA time-zone-aware display and input — rendering "2026-04-15T00:00:00Z" as "2026-04-15 09:00 KST", or making a calendar click emit the civil midnight of that day in the user's zone — use the displayTimezone prop. See the dedicated Timezone concept page.