Aman-Mittal opened a new pull request, #515:
URL: https://github.com/apache/fineract-backoffice-ui/pull/515

   Closes #496.
   
   ## What it does
   
   `formatDateToFineract` handed every string to `new Date()`. ECMAScript 
parses a **date-only** string as UTC midnight, while the getters that build the 
output read **local** time, so at any negative offset the two disagree:
   
   ```
   TZ=America/New_York  '2026-01-15'  ->  14 January 2026
   TZ=America/New_York  '2026-01-01'  ->  31 December 2025
   ```
   
   A string carrying a time or an explicit zone is still left to `new Date()`, 
which reads both correctly. Only the bare `YYYY-MM-DD` form changes.
   
   ## Proof it reached the ledger
   
   Closing an Active group from a Chromium context pinned to 
`America/New_York`, at **07:31 local** — nowhere near midnight, so this is not 
an edge-of-day artifact. The dialog's own default date was left untouched, 
which is the case the issue describes.
   
   The dialog on the pre-fix run:
   
   ![Close Group showing Sep 6, 
2026](https://raw.githubusercontent.com/Aman-Mittal/fineract-backoffice-ui/assets/issue-screenshots/date-utc-shift-dialog-shows-today.png)
   
   | | browser's local date | `closureDate` sent | platform recorded |
   |---|---|---|---|
   | `main` @ `e6b31e4d` | 2026-09-06 | `05 September 2026` | `[2026, 9, 5]` |
   | this branch | 2026-09-06 | `06 September 2026` | `[2026, 9, 6]` |
   
   The user saw "Sep 6, 2026" on screen and the group was closed on the 5th. 
Recordings: 
[before](https://github.com/Aman-Mittal/fineract-backoffice-ui/raw/assets/issue-screenshots/date-utc-shift-before.webm)
 · 
[after](https://github.com/Aman-Mittal/fineract-backoffice-ui/raw/assets/issue-screenshots/date-utc-shift-after.webm).
   
   ## The helper fix alone was not enough
   
   Working through the 55 call sites turned up three more ways a date crossed 
the UTC boundary before or after the helper saw it. Each is in the second 
commit:
   
   - **Five call sites wrapped the value in `new Date()` first** — `group-view` 
×2, `loan-view` ×2, `client-view` ×1. The dialogs behind them return 
`toIsoDate(new Date())`, a bare `YYYY-MM-DD`, so that wrapper re-parsed it as 
UTC before the new branch could apply. This is the path the evidence above 
exercises.
   - **Two dialogs seeded their picker from `new Date().toISOString()`** — 
`center-action-dialog` and `center-meeting-dialog`. Confirming without touching 
the picker sent a different calendar day than the one displayed. Both now use 
`toIsoDate(new Date())`, which the group and client action dialogs already did.
   - **The audit-log filter built its range with `toISOString().split('T')`**, 
which `date-formatter`'s own doc comment warns against — "from today" read as 
tomorrow east of Greenwich and yesterday west of it.
   
   ## Three hand-rolled workarounds are collapsed
   
   The defect was already known locally. `deposit-account-view` and 
`share-account-view` each split the ISO string into parts before formatting, 
both carrying a comment explaining why, and `loan-view` had a private 
`isoToFineractDate` doing the same. All three are the helper's own behaviour 
now.
   
   ## Range checking
   
   `new Date(2026, 12, 45)` does not fail — it rolls forward to 14 February 
2027. Since the caller sends the result to the platform as the user's chosen 
date, a malformed value is refused rather than silently becoming a real one. 
Previously `'2026-13-45'` returned `''`; it still does.
   
   ## The regression guard, and why it is a CI step
   
   Nothing in this project tested west of Greenwich: the runner's clock is UTC 
and `playwright.config.ts` pins `Asia/Kolkata`. Every offset the suite 
exercises is ≥ 0, which is exactly why this shipped — and why no assertion 
running only at UTC can catch its return. The three new cases pass at UTC 
either way.
   
   So `ci.yml` runs the unit suite a second time under `TZ=America/New_York`. 
Reverting only the helper and running that pass:
   
   ```
   × is read as the calendar date it spells, not as UTC midnight
   × does not roll back across a month or a year boundary
   × agrees with the array form of the same date
   
   AssertionError: expected '14 January 2026'   to be '15 January 2026'
   AssertionError: expected '31 December 2025'  to be '01 January 2026'
   ```
   
   It costs about a minute per PR and covers the whole application rather than 
the one helper. Happy to drop it to a single-file run if that trade is not 
wanted — say so and I will.
   
   The pass also found four `...T00:00:00.000Z` fixtures in 
`center-view.component.test.ts` that no dialog in this application produces; 
they passed only because fixture and formatter agreed to read the value as UTC. 
They now carry the calendar date the dialogs actually return.
   
   ## Verification
   
   | | |
   |---|---|
   | `npm run test:unit` | 236 files / 1419 tests, exit 0 |
   | `TZ=America/New_York npm run test:unit` | 236 files / 1419 tests, exit 0 |
   | `npm run build` | clean |
   | `npm run lint` | clean — `date-formatter.ts` no longer needs its 
`unicorn/prefer-number-properties` suppression, pruned via `lint:prune` |
   
   Under the negative offset the suite went 9 failures → 3 → 0 as each layer 
was fixed; the last three were the fixtures above.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to