What are the predefined ISO_* DateTimeFormatter constants, and when would you use them instead of a custom pattern?
answer
- ISO-8601 = unambiguous, locale-neutral, sorts as text
- ISO_LOCAL_* has no zone/offset; ISO_OFFSET_* adds +hh:mm; ISO_ZONED adds [Zone]
- ISO_INSTANT uses 'Z' for UTC, pairs with Instant
- java.time parse/format default to ISO
- Machine data -> ISO; human display -> localized pattern
basics
~10 sConstants like DateTimeFormatter.ISO_LOCAL_DATE or ISO_INSTANT produce/parse standard ISO-8601 text (e.g. 2026-06-20). Use them for machine-to-machine data so you don't reinvent a pattern.
solid answer
~40 sDateTimeFormatter ships with ready-made constants for the ISO-8601 standard: ISO_LOCAL_DATE (2026-06-20), ISO_LOCAL_TIME, ISO_LOCAL_DATE_TIME, ISO_OFFSET_DATE_TIME (with +01:00), ISO_ZONED_DATE_TIME (with a zone like [Europe/Paris]), and ISO_INSTANT (UTC 'Z' form, used by Instant). They are locale-neutral, unambiguous, and round-trippable, so they're ideal for APIs, logs, JSON, and any machine-readable interchange. In fact the parse/format methods on java.time types use ISO formats by default — LocalDate.parse("2026-06-20") works with no formatter argument. You'd reach for a custom ofPattern(...) only for human-facing or legacy formats (e.g. dd/MM/yyyy or a specific locale's month names). Rule of thumb: machine data -> ISO constants; human display -> localized custom or ofLocalizedDate.
go deeper
Knows ISO_LOCAL_DATE-style constants exist and that java.time defaults to ISO when you call parse/format with no formatter.
Can pick the right constant for local vs offset vs zoned vs instant data and explain why ISO is right for machine interchange.
Distinguishes ISO_INSTANT/Instant from zoned/offset types, knows the locale-neutral guarantee, and chooses localized formatters for human display.
Sets serialization conventions across services (ISO everywhere on the wire), avoids cross-service ambiguity, and reasons about sorting/round-trip guarantees of ISO text.
## Background: ISO-8601 **ISO-8601** is the international standard for writing dates and times as text. Its key property is being **unambiguous and locale-independent**: `2026-06-20` always means 20 June 2026, never the American month/day swap. Times look like `14:30:00`, offsets like `+01:00` or `Z` (Z = zero offset = UTC). Putting the largest unit first (year-month-day) also means ISO strings sort correctly as plain text. ## The predefined constants `DateTimeFormatter` exposes static constants that already implement these formats, so you never type the pattern yourself: | Constant | Example output | Pairs with | |---|---|---| | `ISO_LOCAL_DATE` | `2026-06-20` | `LocalDate` | | `ISO_LOCAL_TIME` | `14:30:00` | `LocalTime` | | `ISO_LOCAL_DATE_TIME` | `2026-06-20T14:30:00` | `LocalDateTime` | | `ISO_OFFSET_DATE_TIME` | `2026-06-20T14:30:00+01:00` | `OffsetDateTime` | | `ISO_ZONED_DATE_TIME` | `2026-06-20T14:30:00+01:00[Europe/Paris]` | `ZonedDateTime` | | `ISO_INSTANT` | `2026-06-20T13:30:00Z` | `Instant` | | `ISO_DATE`, `ISO_TIME`, `ISO_DATE_TIME` | flexible (offset optional) | mixed | | `BASIC_ISO_DATE` | `20260620` (no separators) | `LocalDate` | 'Local' means **no time zone / no offset** — just the calendar/clock values. 'Offset' adds a fixed `+hh:mm`. 'Zoned' adds a named region zone in brackets, which also captures daylight-saving rules. ## Default behavior of parse/format The `java.time` types use ISO formats *by default*, so you often need no formatter at all: ```java LocalDate d = LocalDate.parse("2026-06-20"); // ISO_LOCAL_DATE implied String s = LocalDateTime.now().toString(); // ISO_LOCAL_DATE_TIME Instant i = Instant.parse("2026-06-20T13:30:00Z"); // ISO_INSTANT implied ``` ## When to use which - **Machine-to-machine** (REST/JSON payloads, logs, message queues, file formats, sorting keys): use the ISO constants (or the no-arg defaults). They're stable, locale-proof, and round-trip exactly. - **Human display** (a UI showing 'June 20, 2026' or '20/06/2026'): use a custom `ofPattern(...)` or, better, `ofLocalizedDate(FormatStyle.MEDIUM).withLocale(userLocale)` so the format follows the user's locale conventions. ## Common confusion Don't try to parse an offset string with `ISO_LOCAL_DATE_TIME` (it has no offset field) — you'll get a `DateTimeParseException`. Match the constant to the data shape: local vs offset vs zoned vs instant.
- What is the difference between ISO_LOCAL_DATE_TIME and ISO_OFFSET_DATE_TIME?OFFSET includes a UTC offset like +01:00 (or Z), LOCAL does not. Parsing an offset string with the LOCAL formatter throws DateTimeParseException, and vice versa.
- Do you need a formatter to parse "2026-06-20" into a LocalDate?No. LocalDate.parse("2026-06-20") works because java.time defaults to ISO_LOCAL_DATE.
saying these in an interview costs you the question
- Writing a custom yyyy-MM-dd pattern when ISO_LOCAL_DATE already exists
- Parsing an offset/zoned string with a LOCAL constant
- Assuming ISO output is locale-dependent (it isn't)
- Using ISO formats for end-user display instead of localized ones