Day Period Support in JDK 16
JDK 16 Early Access Build 25 (2020/11/18) includes changes for JDK-8247781 (“Day periods support”). As stated in the JDK 16 Early Access Build 25 Release Notes (“Day period support added to java.time formats”), the new functionality “translates day periods defined in Unicode Consortium‘s CLDR.”
In most English-language situations using a “12-hour clock“, the “day periods” might be used instead of the AM (ante meridiem) and PM (post meridiem) designators. The Unicode documentation “Day Period Rule Sets” describes day period rules like this: “Each locale can have a set of day period rules, which determine the periods during a day for use in time formats like ’10:00 at night’, or to select statements like ‘Your email arrived last night.’ If locales do not have dayPeriodRules, the computation of dayPeriods falls back to AM/PM.”
As with most things, it’s perhaps easiest to see this new functionality via code examples and their associated output. The first example shown here is adapted from the JDK 16 Early Access Build 25 Release Notes. Note that the “B” is used in the pattern to specify that a day period is to be used.
01 02 03 04 05 06 07 08 09 10 11 12 | /** * Writes the current day period out to standard output. * * This is based on the example included with the Release Notes */ public void printCurrentDayPeriod() { final String currentDayPeriodStr = DateTimeFormatter.ofPattern( "B" ).format(LocalTime.now()); out.println( "Pattern 'B' (time now): \"" + currentDayPeriodStr + "\"" ); } |
The output for the above code sample when run in evening hours is now shown:
1 | Pattern 'B' (time now): "in the evening" |
The next code sample contains two methods, showing variations of date/time formats using the “B” format pattern letter.
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | /** * Prints representation of supplied {@link ZonedDateTime} with hour, * day period, and time zone details to standard output. * * @param zonedDateTime Date/time that will be written to standard output * and will include hour, day period, and zone details. */ public void printHourDayPeriodAndZone( final ZonedDateTime zonedDateTime) { final String dateTimeStr = DateTimeFormatter.ofPattern( "hh B, zzzz" ).format(zonedDateTime); out.println( "Hour/Day Period/Zone: \"" + dateTimeStr + "\"" ); } /** * Prints representation of supplied {@link ZonedDateTime} with hour, * minutes, day period, and time zone details to standard output. * * @param zonedDateTime Date/time that will be written to standard output * and will include hour, minutes, day period, and zone details. */ public void printHourDayMinutePeriodAndZone( final ZonedDateTime zonedDateTime) { final String dateTimeStr = DateTimeFormatter.ofPattern( "K:mm B z" ).format(zonedDateTime); out.println( "Hour/Minute/Day Period/Zone: \"" + dateTimeStr + "\"" ); } |
The following two lines of output are shown when the two methods above are executed during evening hours:
1 2 | Hour/Day Period/Zone: "08 in the evening, Mountain Standard Time" Hour/Minute/Day Period/Zone: "8:07 in the evening MST" |
Because the output for the examples to this point were all executed in evening hours, the day period (“in the evening”) has been the same for all examples executed above.
The next code listing iterates over each hour of the day to indicate different day period expressions for the different hours when Locale.US is specified. Note that the dates/times constructed in this example have non-zero fractional hours (non-zero minutes, seconds, and nanoseconds).
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 | /** * Prints Day Period phraseology for each of 24 hours of day with * arbitrary minutes, seconds, and nanoseconds to standard output. */ public void printDayPeriodsByHour() { out.println( "===== Hours With Non-Zero Minutes/Seconds/Nanoseconds =====" ); final DateTimeFormatter dateTimeFormat = DateTimeFormatter.ofPattern( "hh B" ); for ( int hour = 0 ; hour < 24 ; hour++) { final OffsetDateTime dateTime = Instant.now().atOffset(ZoneOffset.UTC).withHour(hour); out.println( "Hour " + hour + ": \"" + dateTimeFormat.format(dateTime) + "\"" ); } } |
The output from running the code above shows how different hours correspond to different “day periods” for US.Locale
. Note that this output is based on a date/time with non-zero fractional hours (times are not exact hours).
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ===== Hours With Non-Zero Minutes/Seconds/Nanoseconds ===== Hour 0: "12 at night" Hour 1: "01 at night" Hour 2: "02 at night" Hour 3: "03 at night" Hour 4: "04 at night" Hour 5: "05 at night" Hour 6: "06 in the morning" Hour 7: "07 in the morning" Hour 8: "08 in the morning" Hour 9: "09 in the morning" Hour 10: "10 in the morning" Hour 11: "11 in the morning" Hour 12: "12 in the afternoon" Hour 13: "01 in the afternoon" Hour 14: "02 in the afternoon" Hour 15: "03 in the afternoon" Hour 16: "04 in the afternoon" Hour 17: "05 in the afternoon" Hour 18: "06 in the evening" Hour 19: "07 in the evening" Hour 20: "08 in the evening" Hour 21: "09 at night" Hour 22: "10 at night" Hour 23: "11 at night" |
Because the date/time used in the example above has non-zero fractional hours, the en_US
day period expressions are “at night”, “in the morning”, “in the afternoon”, and “in the evening”.
The next code snippet shows a method that ensures the formatted date/time has “exact hours” (its minutes, seconds, and nanoseconds are all zero).
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 | /** * Prints Day Period phraseology for each of 24 hours of day with * zero minutes, zero seconds, and zero nanoseconds to standard output. */ public void printDayPeriodsByWholeHours() { out.println( "===== Exact Hours =====" ); final DateTimeFormatter dateTimeFormat = DateTimeFormatter.ofPattern( "hh B" ); for ( int hour = 0 ; hour < 24 ; hour++) { final OffsetDateTime dateTime = OffsetDateTime.of( 2020 , 11 , 23 , hour, 0 , 0 , 0 , ZoneOffset.UTC); out.println( "Hour " + hour + ": \"" + dateTimeFormat.format(dateTime) + "\"" ); } } |
When the above code is executed, the following output is seen:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ===== Exact Hours ===== Hour 0: "12 midnight" Hour 1: "01 at night" Hour 2: "02 at night" Hour 3: "03 at night" Hour 4: "04 at night" Hour 5: "05 at night" Hour 6: "06 in the morning" Hour 7: "07 in the morning" Hour 8: "08 in the morning" Hour 9: "09 in the morning" Hour 10: "10 in the morning" Hour 11: "11 in the morning" Hour 12: "12 noon" Hour 13: "01 in the afternoon" Hour 14: "02 in the afternoon" Hour 15: "03 in the afternoon" Hour 16: "04 in the afternoon" Hour 17: "05 in the afternoon" Hour 18: "06 in the evening" Hour 19: "07 in the evening" Hour 20: "08 in the evening" Hour 21: "09 at night" Hour 22: "10 at night" Hour 23: "11 at night" |
The output above is mostly the same as for the output associated with dates/times that had fractional hours, but the whole hours example is different for hour 0 (day period of “midnight”) and hour 12 (day period of “noon”).
For my last example, I’m going to use Dominican Republic/Spanish (“es DO
“) for the Locale
with the same code just demonstrated. Here is that output:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | Hour 0: "12 de la madrugada" Hour 1: "01 de la madrugada" Hour 2: "02 de la madrugada" Hour 3: "03 de la madrugada" Hour 4: "04 de la madrugada" Hour 5: "05 de la madrugada" Hour 6: "06 de la mañana" Hour 7: "07 de la mañana" Hour 8: "08 de la mañana" Hour 9: "09 de la mañana" Hour 10: "10 de la mañana" Hour 11: "11 de la mañana" Hour 12: "12 del mediodía" Hour 13: "01 de la tarde" Hour 14: "02 de la tarde" Hour 15: "03 de la tarde" Hour 16: "04 de la tarde" Hour 17: "05 de la tarde" Hour 18: "06 de la tarde" Hour 19: "07 de la tarde" Hour 20: "08 de la noche" Hour 21: "09 de la noche" Hour 22: "10 de la noche" Hour 23: "11 de la noche" |
Support for “day period” presentation in formatted dates/times provides Java developers with more flexibility in expressing day period details than simply using AM and PM. All code listings shown in this post are available on GitHub.
Published on Java Code Geeks with permission by Dustin Marx, partner at our JCG program. See the original article here: Day Period Support in JDK 16 Opinions expressed by Java Code Geeks contributors are their own. |