@@ -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+ */
112132export 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+ */
182224export 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