Wang1rrr opened a new pull request, #4829:
URL: https://github.com/apache/rocketmq-dashboard/pull/4829

   <!-- Make sure the base branch is `master`: that is the RocketMQ Studio 
trunk. -->
   
   ### Which Issue(s) This PR Fixes
   
   Trivial fix, no issue.
   
   ### Brief Description
   
   Two private copies of `formatTimeMs` formatted the same values - 
`MessageRecord.storeTime` (`number | string`) and trace node `timestamp` 
(`number | string`) - and disagreed with each other and with the rest of the 
console.
   
   `web/src/components/QueueBrowser.tsx`:
   
   ```ts
   export const formatTimeMs = (value: number | string) => {
     const ts = typeof value === 'string' ? Date.parse(value) : value;
     if (!Number.isFinite(ts)) return '-';
     return new Date(ts).toLocaleString('zh-CN', { hour12: false });
   };
   ```
   
   The hardcoded `'zh-CN'` locale produces `2026/9/22 08:36:08`, while every 
other timestamp in the console goes through `utils/format.ts` and renders the 
locale-stable `2026-09-22 08:36:08`. The queue browser is reachable from the 
topic page, so the same message store time is shown in two different formats a 
click apart, and the English console gets a Chinese date layout.
   
   `web/src/pages/instance/message.tsx`:
   
   ```ts
   const formatTimeMs = (value: number | string): string => {
     if (!value) return '-';
     const d = new Date(value);
     ...
   };
   ```
   
   Two problems here:
   
   1. `if (!value)` treats `0` as missing, so the Unix epoch renders as `-`. 
The QueueBrowser test suite already asserts the opposite contract (`preserves 
the Unix epoch timestamp`) - the two copies encoded contradictory invariants 
about the same field.
   2. `new Date(value)` is not validated, so an unparseable string (a provider 
timestamp in a format this browser does not accept) renders as `NaN-NaN-NaN 
NaN:NaN:NaN.NaN` in the message table, the detail drawer and the trace timeline 
instead of the placeholder.
   
   This adds one `formatTimeMs` to `web/src/utils/format.ts`, built on the 
existing `formatDateTime` so it inherits the console-wide `YYYY-MM-DD HH:mm:ss` 
layout and appends `.SSS`, and points both call sites at it. Zero is a real 
timestamp; only a nullish, blank or unparseable value yields `-`. The message 
page keeps its millisecond precision, and the queue browser's timestamp now 
matches the message list it links to.
   
   ### How Did You Test This Change?
   
   ```
   cd web
   npx vitest run src/utils/format.test.ts 
src/components/__tests__/QueueBrowser.test.tsx 
src/pages/instance/__tests__/MessagePage.test.tsx
    Test Files  3 passed (3)
         Tests  38 passed (38)
   
   npx tsc -b        (exit 0)
   npx eslint src/utils/format.ts src/utils/format.test.ts 
src/components/QueueBrowser.tsx src/components/__tests__/QueueBrowser.test.tsx 
src/pages/instance/message.tsx
     (exit 0; one pre-existing react-refresh/only-export-components warning on 
useQueueBrowser, untouched here)
   npx prettier --check --end-of-line auto <same files>
   All matched files use Prettier code style!
   ```
   
   (`--end-of-line auto` because this checkout is CRLF while `.prettierrc` pins 
`endOfLine: lf`; untouched trunk files fail a plain `--check` here for the same 
reason.)
   
   The `describe('formatTimeMs')` block moved from `QueueBrowser.test.tsx` to 
`web/src/utils/format.test.ts` next to the function, keeping both original 
cases and adding the ones the message-page copy violated:
   
   - epoch zero is preserved and matches `/^\d{4}-\d{2}-\d{2} 
\d{2}:\d{2}:\d{2}\.\d{3}$/`
   - `'not-a-date'`, `NaN`, `Infinity`, `null`, `undefined` and `''` all yield 
`-`
   - epoch milliseconds render as `formatDateTime(date) + '.123'`, tying the 
output to the shared formatter
   - a formatted string (`2026-07-31T00:00:00Z`, the shape cloud providers 
return) is accepted
   
   Mutation-checked against **both** removed implementations:
   
   - restoring the message-page body fails 3 tests (`preserves the Unix epoch 
timestamp`, plus the `not-a-date` and `Infinity` placeholder cases);
   - restoring the QueueBrowser `zh-CN` body fails the other 3 (the epoch shape 
assertion and both format assertions).
   
   Each mutation leaves the remaining 15 tests green, so the new cases are the 
ones pinning the behaviour.
   
   ### Checklist
   
   - [x] One coherent change; unrelated modifications are not bundled in
   - [x] Commit subject follows Conventional Commits (`feat:` / `fix:` / 
`refactor:` / `chore:` / `docs:` / `perf:`)
   - [x] Tests added or updated for non-trivial changes, test methods named 
`...Test`
   - [x] New UI text has both Chinese and English entries under `web/src/i18n/` 
(no UI text; the format is now locale-independent)
   - [x] Architecture constraints stay green (`mvn test` runs the ArchUnit 
checks) - no backend change
   - [x] New source files carry the ASF license header (no new source files)
   - [x] Documentation touched where behaviour changed (README / `docs/` / 
in-app help) - none needed
   


-- 
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