iamkun / iamkun/dayjs

Do date format token renders incorrectly (e.g., "17o" instead of "17th") when localizedFormat plugin is enabled

Open
#2,860 1 comment 2 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.