Skip to content

fix: add S and SS fractional-second tokens to format()#3145

Open
JSap0914 wants to merge 1 commit into
iamkun:devfrom
JSap0914:fix/format-S-SS-tokens
Open

fix: add S and SS fractional-second tokens to format()#3145
JSap0914 wants to merge 1 commit into
iamkun:devfrom
JSap0914:fix/format-S-SS-tokens

Conversation

@JSap0914

Copy link
Copy Markdown

Bug

The base format() function only handled SSS (3-digit milliseconds). The S (hundreds digit) and SS (first two digits) tokens were absent from REGEX_FORMAT, so they were never matched — instead they appeared as literal characters in the output:

dayjs('2021-01-01T10:00:00.500').format('S')   // ❌ 'S'   (should be '5')
dayjs('2021-01-01T10:00:00.520').format('SS')  // ❌ 'SS'  (should be '52')
dayjs('2021-01-01T10:00:00.520').format('SSS') // ✅ '520'

This also broke customParseFormat strict mode for S/SS formats. Strict mode re-formats the parsed date and compares it against the original input; because format('S') returned a literal 'S', the comparison always failed:

dayjs('2021-01-01T00:00:00.52',  'YYYY-MM-DDTHH:mm:ss.SS', true).isValid() // ❌ false
dayjs('2021-01-01T00:00:00.5',   'YYYY-MM-DDTHH:mm:ss.S',  true).isValid() // ❌ false

Reported in #1331.

Fix

src/constant.js — extend REGEX_FORMAT from /SSS/ to /S{1,3}/ so that single and double S tokens are matched.

src/index.js — add two new cases to the matches() switch inside format():

Token Returns Example (520 ms)
S Math.floor(ms / 100) '5'
SS Utils.s(Math.floor(ms / 10), 2, '0') '52'
SSS Utils.s(ms, 3, '0') (unchanged) '520'

The token semantics match customParseFormat's existing parse-side expressions (S×100, SS×10, SSS×1), so strict-mode roundtrips now succeed.

Verification

npx jest test/plugin/customParseFormat_S_SS.test.js --no-coverage
PASS test/plugin/customParseFormat_S_SS.test.js
  S and SS format tokens
    base format() support
      ✓ format S returns first digit of milliseconds (hundreds)
      ✓ format SS returns first two digits of milliseconds
      ✓ format SSS still works (3 digits)
    customParseFormat strict mode with S/SS tokens
      ✓ SS strict mode parses 2-digit fractional seconds correctly
      ✓ S strict mode parses 1-digit fractional seconds correctly
      ✓ SSS strict mode still works
Tests: 6 passed

Full suite: 779 tests pass, 0 failures.

Note: this PR was developed with AI assistance.

The base format() function only handled SSS (3-digit milliseconds).
Single S (hundreds digit) and SS (first two digits) were not matched
by REGEX_FORMAT, so dayjs().format('S') and dayjs().format('SS')
returned literal 'S'/'SS' instead of fractional-second values.

This also caused customParseFormat strict mode to reject valid dates
when the format string contained S or SS, because the strict-mode
roundtrip check (date != this.format(format)) would compare an actual
timestamp against a string with literal 'S'/'SS' characters.

Fix:
- Extend REGEX_FORMAT in constant.js from /SSS/ to /S{1,3}/ so that
  S, SS, and SSS are all captured as format tokens.
- Add case 'S' and case 'SS' to the matches() switch in index.js:
    S  → Math.floor(ms / 100)   (hundreds digit, 0–9)
    SS → Math.floor(ms / 10)    (first two digits, zero-padded 00–99)

Fixes: iamkun#1331
Copilot AI review requested due to automatic review settings June 17, 2026 08:50

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.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

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