Resolve localized formats and names per locale - #4
Merged
Conversation
added 4 commits
July 31, 2026 16:59
ofLocalizedDate/Time/DateTime ignored the locale: one hardcoded US-shaped
style-patterns map served every locale, and month/day names came from
strftime, which silently renders English on machines without the locale
installed. Patterns and names now come from bundled tables measured from
the reference JVM, with narrowing (zh-CN -> zh) and a ROOT fallback for
unknown or malformed ids; (Locale. "en_US") is a malformed language
subtag and lands on ROOT, not English. ofLocalized* defers pattern
resolution until .withLocale supplies the locale. Also fixes the y
pattern letter to mean the full year (yy stays two-digit), and joins the
two-arg Locale ctor ("de" "DE" -> "de-DE").
The generated tables had ROOT's wide names spelled out (January, Monday) to make a localized long date read "2014 March 1". CLDR ROOT abbreviates them — the reference JVM renders "Mar" and "Sat" — so spelling them out makes MMMM and EEEE at ROOT disagree with the JVM everywhere, to hit a value nothing needs: Selmer's assertion there accepts either shape and says so in its own comment. Restores the measured values and adjusts the one test expectation.
jolt core's java.text.SimpleDateFormat resolves MMM/MMMM/EEE/EEEE through a :date-names extension point and carries ROOT alone, since it has no locale data of its own. Hand it the tables this library already bundles so an explicit locale renders in its own language there too, not only through DateTimeFormatter. Guarded on the point existing, so a jolt older than it still loads and just keeps ROOT names. The guard swallows the one "not declared" case and rethrows anything else, so a real error in a provider still surfaces.
jolt core declares :number-symbols (String/format's separators) and :currency-data (NumberFormat/getCurrencyInstance) carrying ROOT alone, since it has no locale data. number-data holds both tables for 25 locale ids, measured from the reference JVM and verified by rebuilding the JVM's formatted output from the fields. Registration is now one helper across all three points, each skipped individually if this jolt does not declare it, so the library keeps loading against an older runtime. Note a language-only id has no country and so no currency: the JVM renders de as the generic sign and only de-DE carries the euro. Both are in the table, as measured.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Localized
DateTimeFormatterpatterns and month/day names were a singlehardcoded US-shaped table used for every locale, and names came from libc
strftime, so a French month rendered in English on any machine withoutfr_FRinstalled — a wrong answer that looks like a right one.jolt.time.locale-datanow carries patterns for every (kind, style) pair plusmonth and day names for 14 locale ids, and
jolt.time.number-datacarriesnumber and currency symbols for 25. Every value is measured from the reference
JVM; the currency entries were verified by rebuilding the JVM's formatted output
from the stored fields.
Also registers all three of jolt core's locale extension points —
:date-names,:number-symbolsand:currency-data— which core declares carrying only theroot locale, since it has no locale data of its own. Registration is guarded per
point, so a jolt older than any of them still loads this library and simply keeps
root behaviour there. Needs jolt 0.5.13 for the points to exist.
Resolution narrows (
zh-CN→zh→ root), and an id with no entry lands onroot, matching the JVM. Note ROOT's wide month and day names are the abbreviated
forms — the JVM renders "Mar" for
MMMMat root — and a language-only id has nocountry and therefore no currency, so
deis the generic sign and onlyde-DEcarries the euro. Both are as measured.
Suite: 99 tests, 1037 assertions, 0 failures.