TIME_WINDOW rule dates reach the planner one day earlier than the user picked whenever the time zone of the device is ahead of Europe/Paris (for example Europe/Helsinki, Asia/, Australia/, Pacific/Auckland).
The date picker builds local-midnight Date objects (src/app/shared/day-first-date-adapter.ts, parse). Rules are handed to the planner as those Date objects (planning-calculation.service.ts, request: rules: this.rules.rules), copyDate keeps the instant (leave-planner.service.ts:118), and dateKey() reads the Paris date of that instant (leave-planner.core.ts:599, used for rule windows at :942-943). Local midnight east of Paris is still the previous day in Paris.
The rules panel keeps displaying the picked date (rules-panel.ts:341, toLocaleDateString), so the shift is invisible: the plan silently uses a window starting and ending one day earlier.
Balances are not affected: planning-calculation.service.ts:94-97 formats them with dayjs(...).format("YYYY-MM-DD") from local components before planning.
Evidence
planningDateInParis(new Date(2026, 11, 20)) (the default Christmas window start in rule-service.ts:145) gives:
TZ
planner date
Europe/Paris
2026-12-20
UTC
2026-12-20
America/New_York
2026-12-20
Pacific/Auckland
2026-12-19
The conversion was run; the path from the rules panel to dateKey() was traced by reading, not by running a full plan in an east-of-Paris time zone.
Expected
A TIME_WINDOW rule plans on the calendar dates the user picked, whatever the time zone of the device, matching how balance dates are already handled.
Notes
Saved rules are stored as UTC ISO strings and restored as the same instant (rule-service.ts:195, 214), i.e. the local midnight of the picked date. Converting from local components on the same device recovers the picked date; only a device time-zone change between saving and planning would misread it.
Found while grilling #301 (today marker vs Paris planning date); kept separate because it changes planning results rather than display.
## Problem
TIME_WINDOW rule dates reach the planner one day earlier than the user picked whenever the time zone of the device is ahead of Europe/Paris (for example Europe/Helsinki, Asia/*, Australia/*, Pacific/Auckland).
The date picker builds local-midnight `Date` objects (`src/app/shared/day-first-date-adapter.ts`, `parse`). Rules are handed to the planner as those `Date` objects (`planning-calculation.service.ts`, `request`: `rules: this.rules.rules`), `copyDate` keeps the instant (`leave-planner.service.ts:118`), and `dateKey()` reads the **Paris** date of that instant (`leave-planner.core.ts:599`, used for rule windows at `:942-943`). Local midnight east of Paris is still the previous day in Paris.
The rules panel keeps displaying the picked date (`rules-panel.ts:341`, `toLocaleDateString`), so the shift is invisible: the plan silently uses a window starting and ending one day earlier.
Balances are not affected: `planning-calculation.service.ts:94-97` formats them with `dayjs(...).format("YYYY-MM-DD")` from local components before planning.
## Evidence
`planningDateInParis(new Date(2026, 11, 20))` (the default Christmas window start in `rule-service.ts:145`) gives:
| TZ | planner date |
| --- | --- |
| Europe/Paris | 2026-12-20 |
| UTC | 2026-12-20 |
| America/New_York | 2026-12-20 |
| Pacific/Auckland | **2026-12-19** |
The conversion was run; the path from the rules panel to `dateKey()` was traced by reading, not by running a full plan in an east-of-Paris time zone.
## Expected
A TIME_WINDOW rule plans on the calendar dates the user picked, whatever the time zone of the device, matching how balance dates are already handled.
## Notes
- Saved rules are stored as UTC ISO strings and restored as the same instant (`rule-service.ts:195, 214`), i.e. the local midnight of the picked date. Converting from local components on the same device recovers the picked date; only a device time-zone change between saving and planning would misread it.
- Found while grilling #301 (today marker vs Paris planning date); kept separate because it changes planning results rather than display.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Problem
TIME_WINDOW rule dates reach the planner one day earlier than the user picked whenever the time zone of the device is ahead of Europe/Paris (for example Europe/Helsinki, Asia/, Australia/, Pacific/Auckland).
The date picker builds local-midnight
Dateobjects (src/app/shared/day-first-date-adapter.ts,parse). Rules are handed to the planner as thoseDateobjects (planning-calculation.service.ts,request:rules: this.rules.rules),copyDatekeeps the instant (leave-planner.service.ts:118), anddateKey()reads the Paris date of that instant (leave-planner.core.ts:599, used for rule windows at:942-943). Local midnight east of Paris is still the previous day in Paris.The rules panel keeps displaying the picked date (
rules-panel.ts:341,toLocaleDateString), so the shift is invisible: the plan silently uses a window starting and ending one day earlier.Balances are not affected:
planning-calculation.service.ts:94-97formats them withdayjs(...).format("YYYY-MM-DD")from local components before planning.Evidence
planningDateInParis(new Date(2026, 11, 20))(the default Christmas window start inrule-service.ts:145) gives:The conversion was run; the path from the rules panel to
dateKey()was traced by reading, not by running a full plan in an east-of-Paris time zone.Expected
A TIME_WINDOW rule plans on the calendar dates the user picked, whatever the time zone of the device, matching how balance dates are already handled.
Notes
rule-service.ts:195, 214), i.e. the local midnight of the picked date. Converting from local components on the same device recovers the picked date; only a device time-zone change between saving and planning would misread it.