はじめに
Java16でDateTimeFormatterクラスの書式設定に "B" (period-of-day)が追加されました。
以下のドキュメントには意味として period-of-day 、例が in the morning とあるだけでよくわかりません。
そこで、この書式設定 "B" について実機確認とソースから調べました。
実機確認
各時刻で書式設定 B を指定したときにどのように変換されるかを確認。
確認用ソース
 import java.time.format.DateTimeFormatter;
 import java.time.LocalTime;
 
 public class TestPreiodOfDay  {
   public static void main(String[] args) {
     String s1,s2 ;
     int i ;
     LocalTime  lt   ;
     DateTimeFormatter f = DateTimeFormatter.ofPattern("HH:mm");
     DateTimeFormatter fmt_period = DateTimeFormatter.ofPattern("B");
 
     for ( i = 0 ; i < 24 ; i++ ) {
       lt  =  LocalTime.of(i, 00);
       s1 = lt.format(f);
       s2 = lt.format(fmt_period);
       System.out.println(s1 + " = " + s2);
     }
   }
 }
実行結果
00:00 = midnight
01:00 = at night
02:00 = at night
03:00 = at night
04:00 = at night
05:00 = at night
06:00 = in the morning
07:00 = in the morning
08:00 = in the morning
09:00 = in the morning
10:00 = in the morning
11:00 = in the morning
12:00 = noon
13:00 = in the afternoon
14:00 = in the afternoon
15:00 = in the afternoon
16:00 = in the afternoon
17:00 = in the afternoon
18:00 = in the evening
19:00 = in the evening
20:00 = in the evening
21:00 = at night
22:00 = at night
23:00 = at night
OpenJDKのソースを確認するとこの時間帯とメッセージはハードコーディングされており、固定になっています。
ただ、ロケールによって時間帯やメッセージは変わります。
ロケールが日本語(ja_JP.UTF-8) の場合
System Locale: LANG=ja_JP.UTF-8
実行結果(ロケール ja_JP.UTF-8)
00:00 = 真夜中
01:00 = 夜中
02:00 = 夜中
03:00 = 夜中
04:00 = 朝
05:00 = 朝
06:00 = 朝
07:00 = 朝
08:00 = 朝
09:00 = 朝
10:00 = 朝
11:00 = 朝
12:00 = 正午
13:00 = 昼
14:00 = 昼
15:00 = 昼
16:00 = 夕方
17:00 = 夕方
18:00 = 夕方
19:00 = 夜
20:00 = 夜
21:00 = 夜
22:00 = 夜
23:00 = 夜中
英語では6時から朝(in the morning)なのに対し、日本語では4時から「朝」です。
JDKソース確認
ドキュメントには記載されていませんがソースを見ると "B" 以外に "BBBB" , "BBBBB" の書式も用意されています。
jdk/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java
https://github.com/openjdk/jdk/blob/ddcd851c43aa97477c7e406490c0c7c7d71ac629/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java
 .....
      *  Pattern  Count  Equivalent builder methods
      *  -------  -----  --------------------------
      *    B       1      appendDayPeriodText(TextStyle.SHORT)
      *    BBBB    4      appendDayPeriodText(TextStyle.FULL)
      *    BBBBB   5      appendDayPeriodText(TextStyle.NARROW)
      
 .....
     private void parsePattern(String pattern) {
        .......
                 } else if (cur == 'B') {
                     switch (count) {
                         case 1 -> appendDayPeriodText(TextStyle.SHORT);
                         case 4 -> appendDayPeriodText(TextStyle.FULL);
                         case 5 -> appendDayPeriodText(TextStyle.NARROW);
                         default -> throw new IllegalArgumentException("Wrong number of pattern letters: " + cur);
"BBBB" または "BBBBB" を指定するとメッセージの長さが変わるようですが、en_US ロケールの場合はほとんど変わらずです。
時刻範囲に対するtypeは以下で定義されています。
jdk/make/data/cldr/common/supplemental/dayPeriods.xml
 		<dayPeriodRules locales="en">
 			<dayPeriodRule type="midnight" at="00:00"/>	<!-- midnight -->
 			<dayPeriodRule type="noon" at="12:00"/>	<!-- noon -->
 			<dayPeriodRule type="morning1" from="06:00" before="12:00"/>	<!-- morning -->
 			<dayPeriodRule type="afternoon1" from="12:00" before="18:00"/>	<!-- afternoon -->
 			<dayPeriodRule type="evening1" from="18:00" before="21:00"/>	<!-- evening -->
 			<dayPeriodRule type="night1" from="21:00" before="06:00"/>	<!-- night -->
 		</dayPeriodRules>
 .........
 		<dayPeriodRules locales="ja">
 			<dayPeriodRule type="midnight" at="00:00"/>	<!-- 真夜中 -->
 			<dayPeriodRule type="noon" at="12:00"/>	<!-- 正午 -->
 			<dayPeriodRule type="morning1" from="04:00" before="12:00"/>	<!-- 朝 -->
 			<dayPeriodRule type="afternoon1" from="12:00" before="16:00"/>	<!-- 昼 -->
 			<dayPeriodRule type="evening1" from="16:00" before="19:00"/>	<!-- 夕方 -->
 			<dayPeriodRule type="night1" from="19:00" before="23:00"/>	<!-- 夜 -->
 			<dayPeriodRule type="night2" from="23:00" before="04:00"/>	<!-- 夜中 -->
 		</dayPeriodRules>
type に対するメッセージは以下で定義されています。
jdk/make/data/cldr/common/main/en.xml
 				<dayPeriods>
 					<dayPeriodContext type="format">
 						<dayPeriodWidth type="abbreviated">
 							<dayPeriod type="midnight">midnight</dayPeriod>
 							<dayPeriod type="am">AM</dayPeriod>
 							<dayPeriod type="am" alt="variant">am</dayPeriod>
 							<dayPeriod type="noon">noon</dayPeriod>
 							<dayPeriod type="pm">PM</dayPeriod>
 							<dayPeriod type="pm" alt="variant">pm</dayPeriod>
 							<dayPeriod type="morning1">in the morning</dayPeriod>
 							<dayPeriod type="afternoon1">in the afternoon</dayPeriod>
 							<dayPeriod type="evening1">in the evening</dayPeriod>
 							<dayPeriod type="night1">at night</dayPeriod>
jdk/make/data/cldr/common/main/ja.xml
 				<dayPeriods>
 					<dayPeriodContext type="format">
 						<dayPeriodWidth type="abbreviated">
 							<dayPeriod type="midnight">真夜中</dayPeriod>
 							<dayPeriod type="am">午前</dayPeriod>
 							<dayPeriod type="noon">正午</dayPeriod>
 							<dayPeriod type="pm">午後</dayPeriod>
 							<dayPeriod type="morning1">朝</dayPeriod>
 							<dayPeriod type="afternoon1">昼</dayPeriod>
 							<dayPeriod type="evening1">夕方</dayPeriod>
 							<dayPeriod type="night1">夜</dayPeriod>
 							<dayPeriod type="night2">夜中</dayPeriod>
 ...........
書式設定 Bに対応する主な処理は DayPeriodPrinterParser クラスの format() で行われています。
     static final class DayPeriodPrinterParser implements DateTimePrinterParser {
     .....
 
         public boolean format(DateTimePrintContext context, StringBuilder buf) {
             Long hod = context.getValue(HOUR_OF_DAY);
             if (hod == null) {
                 return false;
             }
             Long moh = context.getValue(MINUTE_OF_HOUR);
             long value = Math.floorMod(hod, 24) * 60 + (moh != null ? Math.floorMod(moh, 60) : 0);
             Locale locale = context.getLocale();
             LocaleStore store = findDayPeriodStore(locale);
             final long val = value;
             final var map = DayPeriod.getDayPeriodMap(locale);
             value = map.keySet().stream()
                     .filter(k -> k.includes(val))
                     .min(DayPeriod.DPCOMPARATOR)
                     .map(map::get)
                     .orElse(val / 720); // fall back to am/pm
             String text = store.getText(value, textStyle);
             buf.append(text);
             return true;
         }
確認環境
CentOS Linux release 7.8.2003 (Core)
openjdk version "16.0.2" 2021-07-20