Skip to content

Commit d11cfd9

Browse files
Docs: HF-24 enrich JSDoc for default stringify guards (LCID design intent)
Replaces the inline rationale block with proper JSDoc on `defaultStringifyDateTime` and `defaultStringifyDuration`. Captures: - The historical pre-HF-24 mis-formatting (`[$USD-409] #,##0.00` → `[$US9-409] #,##0.00` because `D` was treated as a day token). - Why the guard is the deliberate correction, not a regression — every non-currency format remains bit-for-bit compatible. - The `[$SYMBOL-LCID]` vs `[$-LCID]` distinction the regex enforces. - The dispatch contract (`undefined` = defer to next handler) so future callers reason about the fall-through path explicitly. Addresses the design-intent angle raised by Bugbot wave 2 (low-severity inline at format.ts:196). No behavioural change.
1 parent c594bbe commit d11cfd9

1 file changed

Lines changed: 47 additions & 16 deletions

File tree

src/format/format.ts

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,27 @@ function numberFormat(tokens: FormatToken[], value: number): RawScalarValue {
109109
return result
110110
}
111111

112+
/**
113+
* Default `stringifyDuration` callback — formats a duration value against an
114+
* Excel-style time format string (e.g. `[hh]:mm:ss`).
115+
*
116+
* Returns `undefined` for format strings that are not duration formats so the
117+
* dispatcher in `format()` can fall through to other handlers.
118+
*
119+
* **LCID currency-tag guard** — sibling to the same guard in
120+
* `defaultStringifyDateTime`; explicitly returns `undefined` for Excel
121+
* currency tags `[$SYMBOL-LCID]` because the SYMBOL portion contains
122+
* duration-token letters (`H` in CHF/HUF, `m` in AMD/HMD) that
123+
* `parseForDateTimeFormat` would otherwise interpret as time tokens and
124+
* mangle the output. See `defaultStringifyDateTime` for the full
125+
* symbol-vs-locale-modifier rationale and the historical pre-HF-24
126+
* behaviour the guard corrects.
127+
*
128+
* @param time parsed duration value to render
129+
* @param formatArg Excel-style format string
130+
* @returns formatted string, or `undefined` to defer to the next dispatch step
131+
*/
112132
export function defaultStringifyDuration(time: SimpleTime, formatArg: string): Maybe<string> {
113-
// Same LCID-tagged currency guard as defaultStringifyDateTime — Excel
114-
// currency tags `[$SYMBOL-LCID]` contain duration-token letters
115-
// (H in CHF/HUF, m in AMD/HMD) that parseForDateTimeFormat would
116-
// otherwise interpret as time tokens. See defaultStringifyDateTime
117-
// for the symbol-vs-locale-modifier rationale.
118133
if (LCID_CURRENCY_TAG.test(formatArg)) {
119134
return undefined
120135
}
@@ -179,18 +194,34 @@ export function defaultStringifyDuration(time: SimpleTime, formatArg: string): M
179194
return result
180195
}
181196

197+
/**
198+
* Default `stringifyDateTime` callback — formats a date/time value against an
199+
* Excel-style format string (e.g. `YYYY-MM-DD HH:mm:ss`).
200+
*
201+
* Returns `undefined` for format strings that are not date/time formats so the
202+
* dispatcher in `format()` can fall through to `parseForNumberFormat` (or to a
203+
* user-supplied `stringifyCurrency` callback for currency-tagged formats).
204+
*
205+
* **LCID currency-tag guard** — explicitly returns `undefined` for Excel
206+
* currency tags `[$SYMBOL-LCID]` (non-empty SYMBOL portion). Without the
207+
* guard, `parseForDateTimeFormat` greedily consumes letters like `D`/`M`/`S`/`Y`/`H`
208+
* inside the currency code (e.g. `D` in USD, `H` in CHF, `M`+`D` in AMD),
209+
* mangling the output of an `[$USD-409] #,##0.00` format into
210+
* `[$US9-409] #,##0.00` because `D` is read as a day token. The pre-HF-24
211+
* behaviour was to mis-format; the guarded return is the deliberate
212+
* correction, not a regression. Bit-for-bit compatibility is preserved for
213+
* every non-currency format (dates, durations, `$#,##0.00`, etc.).
214+
*
215+
* The guard pattern (`/\[\$[^\-\]]+-/`) requires ≥1 character between `[$`
216+
* and `-` so it distinguishes currency tags (`[$USD-409]`, `[$€-2]`) from
217+
* Excel's locale-only modifier (`[$-409]`, `[$-F800]`), which is valid on
218+
* date/time formats and must continue to flow through this function.
219+
*
220+
* @param dateTime parsed date/time value to render
221+
* @param formatArg Excel-style format string
222+
* @returns formatted string, or `undefined` to defer to the next dispatch step
223+
*/
182224
export function defaultStringifyDateTime(dateTime: SimpleDateTime, formatArg: string): Maybe<string> {
183-
// Skip date/time interpretation for Excel currency formats tagged with
184-
// `[$SYMBOL-LCID]` (non-empty SYMBOL portion). parseForDateTimeFormat
185-
// would otherwise greedily consume characters like D, M, S, Y, H inside
186-
// the currency code (e.g. 'USD' contains D, 'CHF' contains H), mangling
187-
// the output when a user-supplied stringifyCurrency callback opts out by
188-
// returning undefined.
189-
//
190-
// The guard intentionally requires at least one character between `[$`
191-
// and the `-` to distinguish currency tags (`[$USD-409]`, `[$€-2]`) from
192-
// Excel's locale-only modifier (`[$-409]`, `[$-F800]`), which is valid
193-
// on date/time formats and must continue to flow through this function.
194225
if (LCID_CURRENCY_TAG.test(formatArg)) {
195226
return undefined
196227
}

0 commit comments

Comments
 (0)