原文はこちら。
The original article was written by Dustin Marx.
http://marxsoftware.blogspot.com/2020/11/day-period-support-in-jdk-16.html
JDK 16 Early Access Build 25 (2020/11/18) には、JDK-8247781 (day periodのサポート) の変更が含まれています。JDK 16 Early Access Build 25 リリースノート(Day period support added to java.time formats / java.time formats にday periodのサポートが追加されました)に記載されているように、この新機能はUnicode Consortium の CLDR で定義されているday periodを変換します。
JDK 16 Early Access Build 25
https://jdk.java.net/16/
JDK-8247781 Day periods support
https://bugs.openjdk.java.net/browse/JDK-8247781
JDK 16 Early-Access Release Notes
https://jdk.java.net/16/release-notes
Element dayPeriods
https://unicode.org/reports/tr35/tr35-dates.html#dayPeriods
Unicode Consortium
https://home.unicode.org/
CLDR – Unicode Common Locale Data Repository
http://cldr.unicode.org/
英語の場合、ほとんどの状況で12時間時計を使用しているため、AM(午前)とPM(午後)の指示子の代わりにday periodを利用する可能性があります。Unicode文書 “Day Period Rule Sets” では、day periodルールについて次のように説明しています。
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.
Day Period Rule Sets
各ロケールは、一連のday periodルールを持つことができる。これは、’夜の10時’ のような時間形式で使用したり、 ‘あなたの電子メールが昨夜届きました’ のような文を選択したりするために、一日の間の期間を決定するものである。ロケールに dayPeriodRules が設定されていない場合、dayPeriods の計算は AM/PM にフォールバックする。
https://unicode.org/reports/tr35/tr35-dates.html#Day_Period_Rule_Sets
最初のサンプルは、JDK 16 Early Access Build 25 リリースノートから引用したものです。パターンでは、day periodが使われていることを示すためのパターン “B” が使用されていることに注意してください。
DayPeriodDemo.java
https://github.com/dustinmarx/javademos/blob/master/src/dustin/examples/jdk16/datetime/DayPeriodDemo.java
/**
* Writes the current day period out to standard output.
*
* This is based on the example included with the Release Notes
* (https://jdk.java.net/16/release-notes).
*/
public void printCurrentDayPeriod()
{
final String currentDayPeriodStr
= DateTimeFormatter.ofPattern("B").format(LocalTime.now());
out.println("Pattern 'B' (time now): \"" + currentDayPeriodStr + "\"");
}
上記コードを夕方の時間帯に実行した出力結果は以下の通りでした。
Pattern 'B' (time now): "in the evening"
次のコードサンプルには2つのメソッドが含まれています。”B “フォーマットのパターン文字を使用した日付/時刻フォーマットのバリエーションを示しています。
/**
* 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 + "\"");
}
上記2つのメソッドを夕方の時間帯に実行した場合、以下の2行が出力されます。
Hour/Day Period/Zone: "08 in the evening, Mountain Standard Time"
Hour/Minute/Day Period/Zone: "8:07 in the evening MST"
ここまでのサンプルの出力はすべて夕方の時間帯に実行されていたので、実行されたすべての例でday period (“in the evening”) は同じです。
次のサンプルコードは、Locale.USが指定されている場合、異なる時間帯の異なるday period表現を示すために、1日の各時間を反復処理しています。この例で構築された日付/時刻は、ゼロではない分数時間(分、秒、ナノ秒はゼロではない)を持つことに注意してください。
Locale.US
https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/util/Locale.html#US
/**
* 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) + "\"");
}
}
上記コードの実行結果は、USロケールで時間に対応した day period を示しています。この出力は、ゼロではない端数時間を含む日付/時刻に基づいていることに注意してください(時刻は正時ではありません)。
===== 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"
上記の例で使用されている日付/時刻は、ゼロではない端数時間を持つため、en_US でのday period表現は、”at night”、”in the morning”、”in the afternoon”、”in the evening”になります。
次のコード・スニペットは、整形済み日付/時刻が正時(分、秒、ナノ秒はすべてゼロ)を持つことを保証するメソッドです。
/**
* 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) + "\"");
}
}
このコードを実行した結果は以下の通りです。
===== 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"
上記の出力は、端数時間を持つ日付/時刻に関連付けられた出力とほとんど同じですが、時間全体の例では、0時間目(midnight、真夜中)と12時間目(noon、正午)で異なります。
最後にロケールとしてドミニカ共和国/スペイン語 (“es_DO”) を使用した場合の出力結果はこちらです。
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"
整形済み日付/時刻でのday period表現をサポートすることで、Java 開発者は単にAMやPMを使用するよりも柔軟に一日の期間の詳細を表現できるようになります。この記事で紹介したコードはすべて GitHub で公開しています。
(訳注)ja_JPで実施した結果は以下の通りです。
$ java --version
openjdk 16-ea 2021-03-16
OpenJDK Runtime Environment (build 16-ea+26-1764)
OpenJDK 64-Bit Server VM (build 16-ea+26-1764, mixed mode, sharing)
$ java DayPeriodDemo.java ja JP
Setting Locale to ja_JP
Pattern 'B' (time now): "夜"
Hour/Day Period/Zone: "10 夜, 日本標準時"
Hour/Minute/Day Period/Zone: "10:28 夜 JST"
===== Hours With Non-Zero Minutes/Seconds/Nanoseconds =====
Hour 0: "12 夜中"
Hour 1: "01 夜中"
Hour 2: "02 夜中"
Hour 3: "03 夜中"
Hour 4: "04 朝"
Hour 5: "05 朝"
Hour 6: "06 朝"
Hour 7: "07 朝"
Hour 8: "08 朝"
Hour 9: "09 朝"
Hour 10: "10 朝"
Hour 11: "11 朝"
Hour 12: "12 昼"
Hour 13: "01 昼"
Hour 14: "02 昼"
Hour 15: "03 昼"
Hour 16: "04 夕方"
Hour 17: "05 夕方"
Hour 18: "06 夕方"
Hour 19: "07 夜"
Hour 20: "08 夜"
Hour 21: "09 夜"
Hour 22: "10 夜"
Hour 23: "11 夜中"
===== Exact Hours =====
Hour 0: "12 真夜中"
Hour 1: "01 夜中"
Hour 2: "02 夜中"
Hour 3: "03 夜中"
Hour 4: "04 朝"
Hour 5: "05 朝"
Hour 6: "06 朝"
Hour 7: "07 朝"
Hour 8: "08 朝"
Hour 9: "09 朝"
Hour 10: "10 朝"
Hour 11: "11 朝"
Hour 12: "12 正午"
Hour 13: "01 昼"
Hour 14: "02 昼"
Hour 15: "03 昼"
Hour 16: "04 夕方"
Hour 17: "05 夕方"
Hour 18: "06 夕方"
Hour 19: "07 夜"
Hour 20: "08 夜"
Hour 21: "09 夜"
Hour 22: "10 夜"
Hour 23: "11 夜中"