第5章 日付と時刻の新たな API : 問題 12 : 約束の通知
問題
異なるタイムゾーンにある約束を読み込んで、ローカル時刻で1時間前に約束があることをユーザーに通知せよ
例えば、ニューヨークで午前10時に電話会議があったときも、今いる東京で正しいローカル時間に通知を受けることができる
解答
約束とは、タイトルと開始時間(ZonedDateTime
)を持つオブジェクトとする
■ 約束クラス
public class Appointment { /** タイトル */ public final String title; /** 開始時間 */ public final ZonedDateTime time; public Appointment(String title, ZonedDateTime time) { this.title = title; this.time = time; } }
約束を読み込んでSortedSet
に保持する
ソート順は、当然のことながら開始時間の昇順である
■ 約束のコレクション
Set<Appointment> appointments = new TreeSet<Appointment>( (a, b) -> a.time.compareTo(b.time) ); appointments.add(new Appointment("電話会議",~); appointments.add(new Appointment("銀座で接待",~); appointments.add(new Appointment("テレビ会議",~); :
通知のスケジューリングだが、ここでは簡便に
SingleThreadScheduledExecutor
が一定周期で通知スレッドを起動- 通知スレッドは
appointments
をチェックし、1時間後の約束がなければ終了 - 1時間後の約束があれば、ひとつだけ通知して
appointments
から削除
通知は、標準出力に約束の内容を表示するだけとする
■ 通知スレッドのスケジューリング
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); service.scheduleAtFixedRate( () -> { Optional<Appointment> firstAppo = appointments.stream().findFirst(); if (!firstAppo.isPresent()) return; Appointment appo = firstAppo.get(); if (appo.time.isAfter(ZonedDateTime.now().plusHours(1))) return; System.out.println(appo.title + ": " + appo.time); // 通知 appointments.remove(appo); }, 0, 30, TimeUnit.SECONDS ); service.awaitTermination(1, TimeUnit.DAYS);