.NETでは、_時間_という概念をDateTime構造体で扱います。ローカル時刻とUTCを相互に変換するルーチンも用意されています。計算はTimeSpanを使うと行えます。
TimeZoneInfoクラスには、タイムゾーン間の違いを扱うためのルーチンが用意されています。また、TimeZoneInfoクラスには、夏時間を扱いやすくするメソッドも含まれています。
CultureInfoクラスは、ロケールに依存する日時の書式をサポートしています。
クロスプラットフォームでのコーディングを支援するため、RuntimeInformationクラスを使うと、コードがどのオペレーティングシステム(Linux、Windows、OSX)で実行されているかを検出できます。
この演習では、サロンの世界に戻ってきます(datetimes演習で初めて登場しました)。これまでのいくつかのプロジェクトと同じように、担当している別のクライアントが大きな成功を収め、ニューヨークの拠点に加えてロンドンとパリにも店舗を出しました。
UTCの時刻を受け取り、現地時刻として返す静的メソッドAppointment.ShowLocalTime()を実装します。
// For a student in NY
Appointment.ShowLocalTime(new DateTime(2030, 7, 25, 13, 45, 0));
// => {2030, 7, 25, 8, 45, 0}
サロンはそれぞれ自分で予約を受け付けます。入力する時刻は、そのサロンの所在地の現地時刻です。たとえば、ニューヨークのサロンである予約のために13時45分と入力した場合、ランチの直後にクライアントが来ることを想定しています。同じように、ロンドンのサロンで13時45分と入力した場合も、ランチの直後にクライアントが来ることを想定しています。
ニューヨーク、ロンドン、パリのタイムゾーンIDを知っておくと役に立ちます。
Mac(OSX)とLinuxでは、次のとおりです。
Windowsでは、次のとおりです。
所在地と時刻の文字列を受け取り、予約のUTC時刻を返す、静的メソッドAppointment.Schedule()のオーバーロードを実装します。
Schedule()の実装では、ビルドしたコードをLinux、Windows、Macのいずれでも実行できるようにする必要があります。オペレーティングシステムを意識する必要があるのは、これが最初の演習です。上で説明したタイムゾーンIDの違いに対応するために、コードの経路を分ける必要があります。
入力される日時の文字列は、有効であることが保証されています。
Appointment.Schedule("7/25/2030 13:45:00", Location.Paris);
// => {2030, 7, 25, 11, 45, 0}
予約の1日(early)、1時間45分(standard)、30分(late)前に通知を送る、静的メソッドAppointment.GetAlertTime()を実装します。
Appointment.GetAlertTime(new DateTime(2030, 7, 25, 14, 45, 0), AlertLevel.Early);
// => {2030, 7, 24, 14, 45, 0}
過去7日間にサマータイムが始まったか終わった場合にtrueを返す、静的メソッドAppointment.HasDaylightSavingChanged()を実装します。
Appointment.HasDaylightSavingChanged(new DateTime(2020, 3, 30, 14, 45, 0), Location.London);
// => true
現地のスタッフにとって馴染みのある形式で予約を入力できるようにするために、サロンの所在地の既定の形式で日付と時刻を入力できる試験的なルーチンを作成するよう依頼されています。
所在地に適した形式の正しい日時文字列を受け取り、DateTimeオブジェクトに変換する、Appointment.NormalizeDateTime()メソッドを実装します。日時をUTCに変換する処理は行いません。
不正な形式が入力された場合は、値が1/1/1のDateTimeを返します。
Appointment.NormalizeDateTime("25/11/2019 13:45:00", Location.London);
// => {2019, 11, 25, 13, 45, 0}
Appointment.NormalizeDateTime("25/11/2019 13:45:00", Location.NewYork);
// => {1, 1, 1, 0, 0, 0}