Replace moment.js with Intl.DateTimeFormat - batch#6406
Replace moment.js with Intl.DateTimeFormat - batch#6406lkostrowski wants to merge 4 commits intomainfrom
Conversation
Remove moment/moment-timezone imports from useDateLocalize, OrderDraftListDatagrid, VoucherListDatagrid, and CustomerDetails. Use native Intl.DateTimeFormat API instead. - Rewrite useDateLocalize hook with format mapping (ll, lll, llll) - Extract formatDateTime helper in both datagrid modules - Extract formatMonthYear helper in CustomerDetails - Add dedicated unit tests for all extracted functions - Update existing test assertions to match Intl output format Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: 68cf87a The changes in this PR will be included in the next version bump. Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
Pull request overview
Replace Moment/Moment-Timezone usage with native Intl.DateTimeFormat for date/time formatting across UI utilities and corresponding unit tests.
Changes:
- Added
Intl.DateTimeFormat-basedformatDateTimehelpers in order draft + voucher datagrids - Rewrote
useDateLocalizeto map Moment-like tokens (ll,lll,llll) toIntloptions - Added/updated unit tests to validate new formatting output (including comma before time)
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| src/orders/components/OrderDraftListDatagrid/datagrid.ts | Replaces Moment formatting with Intl helper for order draft “created” column |
| src/orders/components/OrderDraftListDatagrid/datagrid.test.ts | Updates assertions + adds formatDateTime unit tests |
| src/hooks/useDateLocalize.ts | Replaces Moment hook with Intl + format-option mapping |
| src/hooks/useDateLocalize.test.tsx | Updates test output to match Intl formatting |
| src/discounts/components/VoucherListDatagrid/datagrid.ts | Replaces Moment formatting with Intl helper for voucher start/end dates |
| src/discounts/components/VoucherListDatagrid/datagrid.test.ts | Adds formatDateTime tests + updates assertions |
| src/customers/components/CustomerDetails/CustomerDetails.tsx | Replaces Moment “MMM YYYY” formatting with Intl helper |
| src/customers/components/CustomerDetails/CustomerDetails.test.ts | Adds tests for formatMonthYear |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #6406 +/- ##
==========================================
+ Coverage 43.13% 43.16% +0.03%
==========================================
Files 2524 2524
Lines 44009 44029 +20
Branches 10011 10398 +387
==========================================
+ Hits 18983 19007 +24
+ Misses 24985 23700 -1285
- Partials 41 1322 +1281 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
| describe("formatMonthYear", () => { | ||
| it("formats date as abbreviated month and year", () => { | ||
| // Arrange & Act | ||
| const result = formatMonthYear("2024-01-15T14:30:00Z"); |
There was a problem hiding this comment.
formatMonthYear is exported as a curried helper (locale) => (date) => string, but the tests call it with a date string as the first argument, so result is a function and these assertions will fail at runtime. Update tests to pass a locale first (e.g. formatMonthYear(Locale.EN)(date)) or adjust the helper signature to match the intended usage.
| (date: string): string => | ||
| new Intl.DateTimeFormat(locale, { | ||
| month: "short", | ||
| year: "numeric", | ||
| }).format(new Date(date)); |
There was a problem hiding this comment.
new Intl.DateTimeFormat(...).format(new Date(date)) will throw a RangeError for invalid dates (e.g. empty/undefined dateJoined), which would crash this render path. Consider validating the parsed date (isNaN(parsed.getTime())) and returning a safe placeholder (or "Invalid date" for parity with moment) instead of throwing; also prefer typing locale as Locale (from @dashboard/components/Locale) rather than string to avoid invalid tags.
| (date: string): string => | |
| new Intl.DateTimeFormat(locale, { | |
| month: "short", | |
| year: "numeric", | |
| }).format(new Date(date)); | |
| (date: string): string => { | |
| const parsed = new Date(date); | |
| if (isNaN(parsed.getTime())) { | |
| // Fallback for invalid dates, matching Moment's "Invalid date" behavior | |
| return "Invalid date"; | |
| } | |
| return new Intl.DateTimeFormat(locale, { | |
| month: "short", | |
| year: "numeric", | |
| }).format(parsed); | |
| }; |
| export function formatDateTime(date: string, locale: Locale): string { | ||
| return new Intl.DateTimeFormat(locale, { dateStyle: "medium", timeStyle: "short" }).format( | ||
| new Date(date), | ||
| ); | ||
| } |
There was a problem hiding this comment.
formatDateTime will throw on invalid input (new Date(date) -> Invalid Date), and then every cell render relies on try/catch. Prefer handling invalid dates inside formatDateTime (e.g., return "-" when isNaN(parsed.getTime())) so callers don’t need exception control flow on hot paths.
| "saleor-dashboard": patch | ||
| --- | ||
|
|
||
| Replaced a few instanced of moment.js usage with native Intl API |
There was a problem hiding this comment.
Typo: “instanced” → “instances”.
| Replaced a few instanced of moment.js usage with native Intl API | |
| Replaced a few instances of moment.js usage with native Intl API |
Scope of the change
Replace moment/moment-timezone with native Intl.DateTimeFormat API across date formatting utilities. Removes external date library dependency and uses modern browser APIs.
Changes:
Rewrote
useDateLocalizehook with format mapping forll,lll, andllllpatternsExtracted
formatDateTimehelpers in OrderDraftListDatagrid and VoucherListDatagrid modulesExtracted
formatMonthYearhelper in CustomerDetails componentAdded 11 new unit tests for date formatting functions across all affected modules
Updated existing test assertions to match Intl.DateTimeFormat output format (includes comma before time)
I confirm I added ripples for changes (see src/ripples) or my feature doesn't contain any user-facing changes
I used analytics "trackEvent" for important events