Pattern-Based Formatters for Date and Time Values – Localization
By Gigi Rosen / February 24, 2024 / No Comments / Formatting and Parsing Messages, Oracle Certifications
Pattern-Based Formatters for Date and Time Values
For more fine-grained formatting and parsing capabilities for temporal objects, we can use the ofPattern() method of the DateTimeFormatter class. This method creates immutable formatters that interpret temporal objects according to a string pattern that is defined using the pattern letters shown in Table 18.15.
Table 18.15 Selected Date/Time Pattern Letters
Date or time component | Pattern letter | Examples |
Year (2: two rightmost digits) Proleptic year: use u Year of era (AD/BC): use y | u uu uuu uuuu uuuuu | 2021; -2000 (2001 BC) 15; 0 (i.e., 1 BC); -1 (i.e., 2 BC) 2021; -2021 (i.e., 2022 BC) 02021 (padding) |
Month in year (1–2: number) (3: abbreviated text form) (4: full text form) | M MM MMM MMMM | 8 08 Aug August |
Day in month | d dd | 6 06 |
Day name in week (1–3: abbreviated text form) (4: full text form) | E EE EEE EEEE | Tue Tue Tue Tuesday |
Hour in day (0–23) | H HH | 9 09 |
Hour in am/pm (1–12) (does not include the AM/PM marker, but required for parsing) | h hh | 7 07 |
Minute in hour (0–59) | m mm | 6 06 |
Second in minute (0–59) | s ss | 2 02 |
Fraction of a second (S) | SSS SSSSSS SSSSSSSSS | 123 123456 123456789 |
Era designator (AD/BC) | G | AD |
Time zone name (1 to 4) | z zzzz | CST Central Standard Time |
Time zone offset (1 to 5) | Z ZZZZ ZZZZZ | -0600 GMT-06:00 -06:00 |
Time zone ID (must be two) | VV | US/Central |
AM/PM marker | a | AM |
Period-of-day (used with temporal values having time units) | B | at night in the morning noon in the afternoon in the evening |
Escape for text | ‘ | ‘T’ prints as T |
Single quote | ” | ‘ |
static DateTimeFormatter ofPattern(String pattern)
This static method creates a formatter using the specified pattern. The set of temporal objects it can be used with depends on the pattern letters used in the specification of the pattern. The letter pattern defines the rules used by the formatter. The method throws an IllegalArgumentException if the pattern is invalid.
Table 18.15 provides an overview of selected pattern letters. All letters are reserved when used in a letter pattern. A sequence of characters can be escaped by enclosing it in single quotes (e.g., “EEEE ‘at’ HH:mm”). Non-letter characters in the string are interpreted verbatim and need not be escaped using single quotes (e.g., “uuuu.MM.dd @ HH:mm:ss”). The number of times a pattern letter is repeated can have a bearing on the interpretation of the value of the corresponding date or time field. The uppercase letter M (Month of the year) should not be confused with the lowercase letter m (minutes in the hour).
A letter pattern can be used to format a temporal object if the temporal object has the temporal fields required by the pattern. The pattern “‘Hour’: HH” can be used to format the hour part of any LocalTime object or a LocalDateTime object, but not a LocalDate.
A letter pattern can be used to parse a string if the string matches the pattern and the letter pattern specifies the mandatory parts needed to construct a temporal object. The pattern “MM/dd/uuuu” can be used to parse the string “08/13/2009” to obtain a LocalDate object, but not a LocalDateTime object. The latter requires the time part as well.
Example 18.7 demonstrates both formatting temporal objects and parsing character sequences for temporal objects using letter patterns. The main() method at (1) calls four methods to format and parse different temporal objects. The formatting of the temporal object can be localized by specifying the desired locale in the main() method.
- The method usingTimePattern() at (2) demonstrates using a letter pattern for the time part to both format a LocalTime and parse a text representation of a LocalTime, respectively. The same pattern is used to format only the time part of a Local-DateTime and a ZonedDateTime, respectively.
- The method usingDatePattern() at (3) demonstrates using a letter pattern for the date part to both format a LocalDate and parse a text representation of a Local-Date, respectively. The same pattern is used to format only the date part of a LocalDateTime and a ZonedDateTime, respectively.
- The method usingDateTimePattern() at (4) demonstrates using a letter pattern for the date and time parts to both format a LocalDateTime and parse a text representation of a LocalDateTime, respectively. The same pattern is also used to parse the text representation of a LocalDateTime to obtain a LocalDate and a LocalTime, respectively.
- The method usingZonedDateTimePattern() at (5) demonstrates using a letter pattern for the date, time, and zone parts to both format a ZonedDateTime and parse a text representation of a ZonedDateTime, respectively. The same pattern is also used to parse the text representation of a ZonedDateTime to obtain a LocalDateTime, a LocalDate, and a LocalTime, respectively.
The usage of letter patterns with the ofPattern() method in Example 18.7 is analogous to the usage of style-based formatters provided by the ofLocalizedType() methods (Table 18.13, p. 1132). The main difference is that letter patterns provide great flexibility in creating customized format styles.
Example 18.7 Formatting and Parsing with Letter Patterns
import java.time.*;
import java.time.format.*;
import java.util.Locale;
public class FormattingParsingWithPatterns {
/** Temporals */
private static LocalTime time = LocalTime.of(12, 30, 15, 99);
private static LocalDate date = LocalDate.of(2021, 4, 28);
private static LocalDateTime dateTime = LocalDateTime.of(date, time);
private static ZoneId zID = ZoneId.of(“US/Central”);
private static ZonedDateTime zonedDateTime = ZonedDateTime.of(dateTime, zID);
public static void main(String[] args) { // (1)
Locale locale = Locale.US;
usingTimePattern(locale);
usingDatePattern(locale);
usingDateTimePattern(locale);
usingZonedDateTimePattern(locale);
}
/** Pattern with time part. */
public static void usingTimePattern(Locale locale) { // (2)
String timePattern = “HH::mm::ss:SSS”;
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern(timePattern)
.localizedBy(locale);
String strTime = time.format(timeFormatter);
LocalTime parsedTime = LocalTime.parse(strTime, timeFormatter);
String strTime2 = dateTime.format(timeFormatter);
String strTime3 = zonedDateTime.format(timeFormatter);
System.out.printf(“Time pattern: %s%n”, timePattern);
System.out.printf(“LocalTime (formatted): %s%n”, strTime);
System.out.printf(“LocalTime (parsed): %s%n”, parsedTime);
System.out.printf(“LocalDateTime (formatted time part): %s%n”, strTime2);
System.out.printf(“ZonedDateTime (formatted time part): %s%n%n”, strTime3);
}
/** Pattern with date part. */
public static void usingDatePattern(Locale locale) { // (3)
String datePattern = “EEEE, uuuu/MMMM/dd”;
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(datePattern)
.localizedBy(locale);
String strDate = date.format(dateFormatter);
LocalDate parsedDate = LocalDate.parse(strDate, dateFormatter);
String strDate2 = dateTime.format(dateFormatter);
String strDate3 = zonedDateTime.format(dateFormatter);
System.out.printf(“Date pattern: %s%n”, datePattern);
System.out.printf(“LocalDate (formatted): %s%n”, strDate);
System.out.printf(“LocalDate (parsed) : %s%n”, parsedDate);
System.out.printf(“LocalDateTime (formatted date part): %s%n”, strDate2);
System.out.printf(“ZonedDateTime (formatted date part): %s%n%n”, strDate3);
}
/** Pattern with date and time parts. */
public static void usingDateTimePattern(Locale locale) { // (4)
String dtPattern = “EE, HH::mm::ss ‘on’ uuuu/MM/dd”;
DateTimeFormatter dtFormatter = DateTimeFormatter.ofPattern(dtPattern)
.localizedBy(locale);
String strDateTime = dateTime.format(dtFormatter);
LocalDateTime parsedDateTime = LocalDateTime.parse(strDateTime,
dtFormatter);
LocalDate parsedDate3 = LocalDate.parse(strDateTime, dtFormatter);
LocalTime parsedTime3 = LocalTime.parse(strDateTime, dtFormatter);
System.out.printf(“DateTime pattern: %s%n”, dtPattern);
System.out.printf(“LocalDateTime (formatted): %s%n”, strDateTime);
System.out.printf(“LocalDateTime (parsed): %s%n”, parsedDateTime);
System.out.printf(“LocalDate (parsed date part): %s%n”, parsedDate3);
System.out.printf(“LocalTime (parsed time part): %s%n%n”, parsedTime3);
}
/** Pattern with time zone, date and time parts. */
public static void usingZonedDateTimePattern(Locale locale) { // (5)
String zdtPattern = “EE, HH::mm::ss ‘on’ uuuu/MM/dd VV”;
DateTimeFormatter zdtFormatter = DateTimeFormatter.ofPattern(zdtPattern)
.localizedBy(locale);
String strZonedDateTime = zonedDateTime.format(zdtFormatter);
ZonedDateTime parsedZonedDateTime
= ZonedDateTime.parse(strZonedDateTime, zdtFormatter);
LocalDateTime parsedDateTime2
= LocalDateTime.parse(strZonedDateTime, zdtFormatter);
LocalDate parsedDate4 = LocalDate.parse(strZonedDateTime,
zdtFormatter);
LocalTime parsedTime4 = LocalTime.parse(strZonedDateTime,
zdtFormatter);
System.out.printf(“ZonedDateTime pattern: %s%n”, zdtPattern);
System.out.printf(“ZonedDateTime (formatted): %s%n”, strZonedDateTime);
System.out.printf(“ZonedDateTime (parsed): %s%n”, parsedZonedDateTime);
System.out.printf(“LocalDateTime (parsed): %s%n”, parsedDateTime2);
System.out.printf(“LocalDate (parsed date part): %s%n”, parsedDate4);
System.out.printf(“LocalTime (parsed time part): %s%n”, parsedTime4);
}
}
Probable output from the program:
Time pattern: HH::mm::ss:SSS
LocalTime (formatted): 12::30::15:000
LocalTime (parsed): 12:30:15
LocalDateTime (formatted time part): 12::30::15:000
ZonedDateTime (formatted time part): 12::30::15:000
Date pattern: EEEE, uuuu/MMMM/dd
LocalDate (formatted): Wednesday, 2021/April/28
LocalDate (parsed) : 2021-04-28
LocalDateTime (formatted date part): Wednesday, 2021/April/28
ZonedDateTime (formatted date part): Wednesday, 2021/April/28
DateTime pattern: EE, HH::mm::ss ‘on’ uuuu/MM/dd
LocalDateTime (formatted): Wed, 12::30::15 on 2021/04/28
LocalDateTime (parsed): 2021-04-28T12:30:15
LocalDate (parsed date part): 2021-04-28
LocalTime (parsed time part): 12:30:15
ZonedDateTime pattern: EE, HH::mm::ss ‘on’ uuuu/MM/dd VV
ZonedDateTime (formatted): Wed, 12::30::15 on 2021/04/28 US/Central
ZonedDateTime (parsed): 2021-04-28T12:30:15-05:00[US/Central]
LocalDateTime (parsed): 2021-04-28T12:30:15
LocalDate (parsed date part): 2021-04-28
LocalTime (parsed time part): 12:30:15