Date & time picker
Clinical time is not calendar time. It carries a timezone, it cannot run forwards, it has two ambiguous hours a year, and getting it wrong changes what a trend means.
Overview
Almost every clinical decision this system supports is a decision about change over time: ST elevation compared with a prior, troponin across a 0/1 h interval, how long a patient has waited. All of it rests on timestamps being unambiguous, ordered and correctly zoned — and a picker is where a human introduces the error.
Unambiguous
ISO 8601, 24-hour, with the timezone visible. A date that means two things depending on where you trained is not a date.
Bounded
Observations cannot be in the future. Constraints are stated before entry, not discovered after it.
Typeable
The calendar is an aid. A clinician who knows the date types it — six taps to reach last Tuesday is a failure of the control, not of the user.
Anatomy
| Element | Rule |
|---|---|
| Text field | The primary input. Accepts a typed ISO date and is never read-only in favour of the calendar. |
| Format hint | YYYY-MM-DD, always visible, plus the timezone the value is interpreted in. |
| Calendar | An aid. Marks today distinctly from the selection, and disables what is out of range rather than silently rejecting it. |
| Footer | Restates the selection in full, and names the active constraint. |
Format
04/12/57 is 4 December to a European clinician and 12 April to an American one,
and both readings are confident. Dates are entered, displayed, stored and printed as
YYYY-MM-DD throughout — no locale-aware formatting, no input masks that reorder
fields, no two-digit years. The same rule as
Patient header.
- 24-hour time.
14:26, never2:26 PM. Removes the am/pm class of error entirely. - Seconds where clinically relevant. ECG acquisition and alarm timestamps carry seconds; an appointment does not.
- Never abbreviate a month to letters. "Aug" does not translate and sorts wrongly.
- Tabular numerals, so timestamps align in a column — see Typography.
Timezone is part of the value
A clinical timestamp without a zone is not a timestamp. Three rules:
- Store UTC, display local, name the zone. The displayed zone is stated beside the value or in the field hint — never assumed from the browser without saying so.
- Display in the zone of the site of care, not the reader's. A cardiologist reviewing from another country must see the times the ward saw, or every interval they compute is wrong.
- Never mix zones in one view. If a record genuinely spans sites, each timestamp carries its zone explicitly and the mixing is stated.
At the end of daylight saving, one local hour occurs twice. A 0/1 h troponin interval spanning it can appear to run backwards, or to be two hours long. The picker resolves this by storing UTC and, where a local time is ambiguous, asking which occurrence is meant rather than guessing. At the spring transition, times inside the skipped hour are rejected with an explanation — they did not exist.
Constraints
| Field kind | Constraint | Behaviour |
|---|---|---|
| Observation — acquisition, sample drawn | Not in the future | Future dates disabled in the calendar; typed future dates rejected with the reason. |
| Date of birth | Not in the future; plausible age range | Outside the range confirms rather than rejects — see Text field. |
| Scheduled — repeat sampling, follow-up | Usually future | Past dates permitted but confirmed, since back-dating is sometimes correct. |
| Range — trend window | Start ≤ end | Selecting an end before the start reorders them and says so; it never silently swaps. |
Constraints are stated before entry, not after. A hint reading "not in the future" costs nothing; discovering it after typing costs a re-entry at the worst moment.
Relative and absolute time
"4 min ago" is easier to read and harder to verify. The rule follows the consequence:
- Relative time for elapsed duration a clinician is monitoring — waiting time in a queue, countdown to a re-alert. It answers "how long", which is the actual question.
- Absolute time for anything recorded — acquisition, acknowledgement, assessment, notification. The audit trail is absolute, always, with seconds.
- Never relative alone on a clinical event. Where relative is shown for
readability, the absolute time sits beside it:
4 min ago · 14:26:38. - Relative time updates live, or it is a lie within a minute — but the update never animates and never reflows the row.
Unambiguous format, named zone, constraint stated before entry.
Locale-ambiguous order, two-digit year, am/pm, no timezone, no constraint. Four independent ways to record the wrong moment.
Do's and don'ts
Unambiguous format, named zone, constraint stated before entry.
Locale-ambiguous order, two-digit year, am/pm, no zone, no constraint. Four ways to record the wrong moment.
Accessibility
- The text input is the control; the calendar supplements it. A picker that can only be operated by clicking a grid is unusable for many keyboard and switch users, and slow for everyone who knows the date.
- Full keyboard grid — arrows move by day, Page Up/Down by month, Home/End to week bounds, Esc closes and returns focus to the field.
- Each day has a full accessible name — "Tuesday 11 August 2026", not "11" — and disabled days announce why.
- Today and selected are visually distinct and distinguished by more than colour: today by border, selection by fill plus weight.
- Touch targets obey the physical floor from Scaling, which on a cart means a larger calendar, not smaller days.
- Never
type="date"alone where the format matters — its rendering and behaviour vary by browser and locale, which is precisely the ambiguity this page exists to remove.
Outcomes of use
What this contributes to, in the terms of Usability & context of use. These are attributes believed to contribute to an outcome; the outcome itself is settled by observing real use in a specified context, not by this page.
- Effectiveness — the recorded moment is the moment that happened. Every interval, trend and audit entry downstream depends on it.
- Efficiency — typing a known date beats navigating to it. The calendar exists for the cases where the clinician is counting backwards from today.
- Satisfaction — no second-guessing whether the field meant day-month or month-day, which is a small, constant tax in any multinational deployment.
Clinical safety notes
Trace these in your risk file (ISO 14971) and usability engineering file (IEC 62366-1).
- ISO 8601 and 24-hour only. Mitigates: day/month transposition and am/pm error — the two most common date entry faults in multinational deployments.
- Timezone named and stored as UTC. Mitigates: intervals computed across zones being wrong by hours.
- Ambiguous DST hour resolved by asking. Mitigates: an interval appearing to run backwards, or a duplicate-hour sample being ordered wrongly.
- Observations cannot be future-dated. Mitigates: an impossible timestamp corrupting a trend or an audit sequence.
- Constraints stated before entry. Mitigates: re-entry under time pressure.
- Absolute time on every recorded event. Mitigates: an audit trail that cannot be reconstructed later.
- Range order corrected explicitly, never silently. Mitigates: a trend window inverted without the clinician knowing.
Implementation
$ npx shadcn@latest add https://md.notjustany.tech/r/date-picker.json
<DateTimeField
label="ECG acquired"
kind="observation" // disallows future values
precision="second"
zone="Europe/Vienna" // site of care, not the reader's browser
value={value} // always UTC on the wire
onChange={setValue}
/>
// Timezone is not optional, because a clinical timestamp without one
// is not a timestamp.
if (!zone) {
throw new Error(
"[DateTimeField] `zone` is required. Pass the site of care's zone — " +
"never infer it from the reader's browser."
)
}
| Prop | Type | Default | Notes |
|---|---|---|---|
kind | observation | birth | scheduled | range |
— | Required. Sets the constraint set. |
zone | IANA zone | — | Required. Never inferred. |
precision | day | minute | second |
minute | second for acquisitions and audit events. |
value | ISO 8601 UTC | — | Local time is a rendering, never the stored value. |
Related
- Text field — the input underneath, and its validation rules.
- Patient header — the same date formatting.
- Typography — tabular numerals.
- Clinician override — where absolute timestamps land.