Files
jobtrackingapp/docs/i18n/DATE_PICKER_CALENDAR_DAY.md
T

3.9 KiB

Date-picker calendar-day preservation

11 November 2026. Baseline ec57a24d77854bb416c9ea02b8b371be3e5554c0, isolated branch codex/i18n-deadline-picker-date.

The Add and Edit job dialogs passed date-only strings through new Date(value), which interprets a literal YYYY-MM-DD at UTC midnight. In Los Angeles, opening 23 November displayed the 22nd. Their picker change handlers then used toISOString().slice(0, 10). Selecting local midnight on 23 November in Oslo or Kiritimati submitted the 22nd.

The existing wrapper pairs now use installed date-fns parseISO for literal dates and format(value, "yyyy-MM-dd") for the picker's local Date output. Non-literal parsing retains new Date(value). Empty and invalid picker values retain their existing clearing behaviour. Edit's separate legacy toDateInputValue loading policy is preserved.

The affected callers are Add's applied date and deadline, and Edit's applied date, status-change date, reply date, follow-up date and deadline. All seven controls are date pickers backed by date-only state and request values. Revision and submit handlers are retained. There is no backend, timestamp serialization, dependency or migration change.

Verification

The new component regression drives the actual Add/Edit state and conversion handlers with a picker test double implementing MUI's local-Date callback contract. Each run starts a new Jest process with the recorded timezone. It checks EN/NB values, a full create/save payload, source revision, five Edit/two Add controls, clearing, invalid picker values and an offset timestamp using the existing legacy loading policy.

Process timezone Before fix After fix
America/Los_Angeles 5 failed 5 passed
Europe/Oslo 4 failed, 1 passed 5 passed
Pacific/Kiritimati 4 failed, 1 passed 5 passed

These are the same five cases executed in three environments. The nearby run passed 21 cases across date-picker, edit-revision, quick-capture and native file-input suites, including those same five cases. TypeScript without emit, ESLint on the three changed files and tracked source whitespace checks passed. The cached evidence check flagged the original TypeScript receipt's blank line at EOF. That raw receipt is retained unchanged in evidence/date-picker-calendar-day/.

Actual MUI browser interaction, screenshots, native devices and provider/API server verification were not run in this isolated increment. The root integration owner will qualify the rendered picker separately. Final I18N, A3, security and release acceptance remain open.

Other reviewed date contracts

CalendarAgenda validates its date-only response, parses it at UTC noon and explicitly formats in UTC. The reviewed 23 November value stayed on the 23rd in all three zones. Its backend groups by the stored calendar date and explicitly retains the legacy timezone/precision limitation.

CompaniesTable formats next-contact and relationship dates using the viewer's local timezone. Its edit form takes the raw first ten characters. Literal 2026-11-23 therefore displays as the 22nd in Los Angeles, while 2026-11-23T23:30:00Z displays as the 24th in Oslo and opens as the 23rd in the editor. The backend fields remain legacy DateTime? with no precision discriminator. The current locale test covers a noon UTC timestamp. These display/loading cases require a qualified date-versus-timestamp contract before a broader change.

The Jobs table similarly formats a literal deadline through local Date, and its current test expects that expression. Edit's retained toDateInputValue can also move an unspecified midnight timestamp back a day in positive zones. These are separate legacy precision/loading findings. This fix does not claim their closure or reconstruct missing timezone metadata.

Rollback reverts the two wrapper changes and their regression package. Existing persisted dates are not rewritten.