Do date format token renders incorrectly (e.g., "17o" instead of "17th") when localizedFormat plugin is enabled
- Dominant language
- JavaScript
- Stars
- 48.7k
- Forks
- 2.5k
- PR merge metrics
- No merged PRs in 30d
Description
When using the `Do` date format token (for day of the month with ordinal suffix) along with the `localizedFormat` plugin enabled, the output for the ordinal suffix is incorrect for some numbers (e.g., 17 renders as "17o" instead of the expected "17th" for the 'en' locale). Disabling the `localizedFormat` plugin resolves the issue, and `Do` renders correctly. Direct calls to `dayjs().localeData().ordinal()` return the correct bracketed string (e.g., `[17th]`).
**Expected behavior**
With the 'en' locale active and `localizedFormat` enabled, `dayjs().format('MMMM Do, YYYY')` for a date like '2025-04-17' should output "April 17th, 2025".
**Current behavior**
With the 'en' locale active and `localizedFormat` enabled, `dayjs().format('MMMM Do, YYYY')` for '2025-04-17' outputs "April 17o, 2025".
**Steps to reproduce**
1. Include `dayjs.min.js`, `plugin/localeData.js`, and `plugin/localizedFormat.js` (ensure versions are compatible).
2. Extend dayjs with both plugins:
```javascript
// Assuming dayjs_plugin_localeData and dayjs_plugin_localizedFormat
// are available globally from the script tags
dayjs.extend(dayjs_plugin_localeData);
dayjs.extend(dayjs_plugin_localizedFormat);
```
3. Set the locale to 'en':
```javascript
dayjs.locale('en');
```
4. Format a date where the day requires the "th" suffix (e.g., 17th):
```javascript
const date = dayjs('2025-04-17');
const formattedString = date.format('MMMM Do, YYYY');
console.log(formattedString); // Outputs "April 17o, 2025"
// Diagnostic checks:
console.log(date.localeData().ordinal(17)); // Correctly outputs "[17th]"
console.log(date.format('Do')); // Incorrectly outputs "17o"
```
5. (Verification) Comment out `dayjs.extend(dayjs_plugin_localizedFormat);`.
6. Re-run step 4. The output will now be the correct "April 17th, 2025".
**Possible cause**
It appears that the `localizedFormat` plugin, by overriding the core `.format()` method, interferes with the correct processing of the `Do` token, specifically how the bracketed result from `localeData().ordinal()` (like `[17th]`) is handled by the formatting engine. The `localizedFormat` plugin itself doesn't explicitly target the `Do` token, but its wrapping/modification of the format string seems to break the standard handling of `Do`.
**Workaround**
A working solution is to manually call `localeData().ordinal()` and format the date string without using the `Do` token:
```javascript
const dayJsDate = dayjs('2025-04-17');
const dayNumber = dayJsDate.date();
// Get ordinal string (e.g., "[17th]") and remove brackets
const ordinalString = dayJsDate.localeData().ordinal(dayNumber).replace(/^\[|\]$/g, ''); // Should be "17th"
// Format using components
const finalFormattedDate = `${dayJsDate.format('MMMM')} ${ordinalString}, ${dayJsDate.format('YYYY')}`;
// finalFormattedDate is now "April 17th, 2025"
```
**Information**
- Day.js Version - 1.11.13
- OS: Archlinux
- Browser Chromium Version 129.0.6668.89 (Official Build) Arch Linux (64-bit)
Contributor guide
Research direction
Reproduce the output using the localeData and localizedFormat plugins with the English locale and the `Do` token. Start by inspecting the localizedFormat plugin's format wrapper and the core handling of the bracketed ordinal result; done means `MMMM Do, YYYY` produces `April 17th, 2025` with localizedFormat enabled without breaking the existing behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- localization
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100