まえがき
先日の JJUG CCC 2017 Spring で以下の発表を行いました。
このセッションでの質問で「この10個はどうやって見つけたのですか?」の質問を頂きました。もともと知っていたのと、今回のセッションをやるにあたり見直してみたというのもあるのですが、やはり普段何かしらJavaコアAPIのソースを読んだり何か試してみたりということが地味に効いているのかもと、思いました。
今日の話題
さて、最近以下のことがふと気になったのでやってみました。
Hを多く書いてみる
3名の方からご回答頂きました。意見は割れました。私は2番目だと思っていました。
しかし現実は違いました。
コアAPIの実装を見てみるとこうなっていました。(8u131のソースを抜粋)
case 'd':
case 'h':
case 'H':
case 'k':
case 'K':
case 'm':
case 's':
if (count == 1) {
appendValue(field);
} else if (count == 2) {
appendValue(field, count);
} else {
throw new IllegalArgumentException("Too many pattern letters: " + cur);
}
break;
2文字しか受け付けないので3文字以上はアウトということですね。
ではHが2個なら大丈夫か?→場合により例外が出る
そこで次の問題がこれです。
これも実装を見てました。
@Override
public long getLong(TemporalField field) {
if (field instanceof ChronoField) {
switch ((ChronoField) field) {
case NANO_OF_SECOND: return nanos;
case MICRO_OF_SECOND: return nanos / 1000;
case MILLI_OF_SECOND: return nanos / 1000_000;
case INSTANT_SECONDS: return seconds;
}
throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
}
return field.getFrom(this);
}
今回取得しようとしているHOUR_OF_DAY
はChronoField
なので、上記の
if (field instanceof ChronoField) {
この条件を満たすためこのif
文の中に入ってきます。そして、switch
の中に該当するフィールドがないのであえなくアウト、ということになります。
つまり、時間を取りたい場合はLocalDateTime
などHOUR_OF_DAY
がサポートされているクラスのインスタンスでないとダメということですね。これは勉強になりました。
付録
テストに使用したコードを載せておきます。個人用に書いたのでコメントもなく、2つのテスト切り替えもコメントを外して実行、といったあまりキレイじゃないやり方でお恥ずかしい。
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
*
*/
public class FormatterTest {
/**
*
* @param arguments
*/
public static void main(String[] arguments) {
//System.out.println(DateTimeFormatter.ofPattern("HH").format(Instant.now()));
System.out.println(DateTimeFormatter.ofPattern("HHHH").format(LocalDateTime.now()));
}
}