Skip to content

fix: mixed-case "MS" unit resolves to millisecond instead of crashing get() - #3184

Open
koding88 wants to merge 1 commit into
iamkun:devfrom
koding88:fix/mixed-case-ms-unit
Open

fix: mixed-case "MS" unit resolves to millisecond instead of crashing get()#3184
koding88 wants to merge 1 commit into
iamkun:devfrom
koding88:fix/mixed-case-ms-unit

Conversation

@koding88

Copy link
Copy Markdown

Summary

Units are documented as case-insensitive, but mixed-case forms of ms broke in three different ways:

const d = dayjs('2024-06-15T12:34:56.789')

d.get('MS')        // TypeError: this[...] is not a function  (crash)
d.set('MS', 500)   // silent no-op — milliseconds stay .789
d.startOf('MS')    // clone-only no-op
d.add(1000, 'MS')  // worked only by a double-fallthrough accident

While every other unit resolves correctly in any casing ('HOUR', 'Day', 'MONTH'…).

Root cause

prettyUnit (src/utils.js) consulted the special map before lowercasing and then stripped a trailing s:

special['MS']                       /* undefined */
|| 'MS'.toLowerCase()               /* 'ms'      */
   .replace(/s$/, '')               /* 'm'       */   minute string!

get('MS') then called this['m'](), which does not exist on the prototype (the minute getter is registered under the full name 'minute') and threw.

Fix

Look up the special map again after lowercasing:

const lower = String(u || '').toLowerCase()
return special[u] || special[lower] || lower.replace(/s$/, '')

Exact-key mappings are still consulted first, so every existing resolution is unchanged ('D''date', 'm''minute', 'minutes''minute', …). Only the broken mixed-case ms family changes behavior — to match its lowercase form, as the docs already promise.

Tests

  • PrettyUnit: MS / Ms / mSmillisecond
  • get-set: get('MS'), set('MS'|'Ms', n) work; startOf('MS') is identical to startOf('ms')

Checklist

  • npm run lint clean
  • npm test green — 94 suites / 797 tests, line coverage unchanged at 100%

prettyUnit consulted the special map before lowercasing, then
stripped a trailing 's', so 'MS'/'Ms'/'mS' resolved to the string
'm'. Consequences while every other unit was case-insensitive:

- get('MS') threw TypeError (this.m is not a function)
- set('MS', n) was a silent no-op
- startOf/endOf('MS') were clone-only no-ops

Look up the special map again after lowercasing so mixed-case ms
behaves exactly like 'ms'.
Copilot AI lite review requested due to automatic review settings August 24, 2026 16:06

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The change is narrowly scoped to unit normalization, preserves existing mappings by checking exact keys first, and is covered by targeted unit and integration tests.

Pull request overview

Fixes prettyUnit so mixed-case millisecond units ("MS", "Ms", "mS") resolve to "millisecond" consistently (as documented) instead of incorrectly collapsing to "m" (minute) and causing crashes/no-ops in APIs like get, set, and startOf.

Changes:

  • Update prettyUnit to re-check the special-unit map after lowercasing the input (fixing the mixed-case "ms" family).
  • Add unit tests covering mixed-case ms variants in PrettyUnit.
  • Add integration-style tests verifying get('MS'), set('MS'|'Ms', n), and startOf('MS') behave like their lowercase equivalents.
File summaries
File Description
src/utils.js Adjusts prettyUnit resolution order to correctly handle mixed-case millisecond units.
test/utils.test.js Adds direct prettyUnit coverage for "MS", "Ms", and "mS".
test/get-set.test.js Adds coverage ensuring get/set/startOf work correctly with mixed-case millisecond units.
Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants