Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/__tests__/format.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -271,4 +271,13 @@ describe("format with a timezone", () => {
})
).toBe("12/19/89, 1:30:10 AM -0600")
})
it("does not throw when locale already contains a Unicode extension subtag (#68)", () => {
// ar-u-nu-arab requests Arabic-Indic numerals via BCP 47 Unicode extension.
// Previously, format() appended "-u-hc-h23" producing the invalid tag
// "ar-u-nu-arab-u-hc-h23" which throws "Invalid language tag".
expect(() => format("2024-01-15", "YYYY/MM/DD", "ar-u-nu-arab")).not.toThrow()
// The formatted output should use Arabic-Indic digits (٢٠٢٤, etc.)
const result = format("2024-01-15", "YYYY/MM/DD", "ar-u-nu-arab")
expect(result).toBe("٢٠٢٤/٠١/١٥")
})
})
9 changes: 8 additions & 1 deletion src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,14 @@ function createPartMap(
const genitiveParts: Part[] = []

function addValues(requestedParts: Part[], hour12 = false) {
const preciseLocale = `${locale}-u-hc-${hour12 ? "h12" : "h23"}`
// Use Intl.Locale to merge the hourCycle extension into the locale tag.
// Plain string concatenation (e.g. `${locale}-u-hc-h23`) produces an
// invalid BCP 47 tag when the locale already contains a Unicode extension
// block (e.g. "ar-u-nu-arab"), because a tag may only have one "-u-" block.
// Intl.Locale merges extensions correctly into a single "-u-" subtag.
const preciseLocale = new Intl.Locale(locale, {
hourCycle: hour12 ? "h12" : "h23",
}).toString()
valueParts.push(
...new Intl.DateTimeFormat(
preciseLocale,
Expand Down