Files
java-core-examples/datetimeformatter/README.md
T

2.5 KiB

datetimeformatter

Companion code for the ankurm.com post "DateTimeFormatter Cheat Sheet: Patterns, the yyyy vs YYYY Bug, Locales and ISO Formats." Module in java-core-examples, the Java-core series. All explanation lives in the post; this module holds the code and the captured output.

Versions this was built and tested against

Component Version Notes
JDK 25.0.5+8 (Temurin, LTS) java.time arrived in Java 8. Locale data is CLDR; the narrow no-break space before AM/PM comes from the CLDR 42 update that shipped in JDK 20.
JUnit Jupiter 5.11.0
Maven 3.9.11

Quickstart

export JAVA_HOME=/path/to/jdk-25
mvn compile
scripts/run.sh WeekYearBugDemo      # one demo
scripts/run-all.sh                  # regenerate every file in output/

What's in here

File What it shows Output
PatternLettersDemo.java About fifty pattern strings applied to one fixed moment: how repeat count changes M, E, S, z, X, O, and what A, n, e, B, w, W give. output/01
WeekYearBugDemo.java yyyy vs YYYY vs uuuu: the same date in four locales, and how many days in 2020-2030 each locale gets wrong. output/02
LocaleDemo.java en_IN, hi_IN, mr_IN; Sept; lowercase pm; the U+202F character before AM/PM the parse failure it causes, and parseLenient() as the fix. output/03
ParsingDemo.java STRICT / SMART / LENIENT on 31-02-2026, yyyy vs uuuu under STRICT, digit counts, two-digit years, case sensitivity, and SimpleDateFormat for comparison. output/04
IsoFormatsDemo.java Every predefined ISO constant on one value. output/05
ErrorsDemo.java The eleven exceptions people actually meet, with the real messages. output/06
ThreadSafetyDemo.java One shared SimpleDateFormat vs one shared DateTimeFormatter, 8 threads. Counts for SimpleDateFormat drift between runs. output/07
DateTimeFormatterTest.java Pins every claim above as an assertion, 18/18 passing. output/08

Notes worth knowing before reading the post

  • YYYY is the week-based year. On 2026-12-29 it prints 2027 in en_US and en_IN and 2026 in en_GB and fr_FR (output/02).
  • The default resolver style is SMART, which parses 31-02-2026 as 28 February 2026 instead of failing (output/04).
  • ofLocalizedTime(SHORT) puts U+202F, not a space, before PM, so a typed 3:30 PM does not parse back (output/03).

License

MIT - see the repo-wide LICENSE.