Calenderは主に日付と時間の計算を行う際に使用する構造体です。
環境
この記事の情報は次のバージョンで動作確認しています。
【Swift】5.2
【iOS】13.4.1
【macOS】Catalina バージョン 10.15.4
日時計算は難しい
1分は60秒、1時間は60分、1日は24時間、1年は365日のように誰もが知っている法則を使えば、日時計算はそれほど難しくないように思えます。
でも、実は例外パターンがいくつもあります。
- 4年に1回訪れる「うるう年」は、1年が366日です。しかも厳密には4年に1回ではなかったりします。
- 同じように、何年かおきに「うるう秒」といって1分が61秒になる瞬間があります。
- 海外等で採用されている、夏時間(サマータイム)の切り替わりタイミングでは1日が24時間では無い日が存在します。
日時計算を正確に行うには、このような例外パターンを全て考慮する必要がありますので、独自でロジックを組むのはとても大変です。
Calendar構造体を使うと、これらの例外を考慮した日時計算が可能です。
Date構造体を生成する
特定の日時を示すDate構造体を生成するのには、Calendarのdateメソッドを使用します。
1 2 3 4 5 6 7 |
/// 西暦(gregorian)カレンダーを生成 var calendar = Calendar(identifier: .gregorian) /// 日時を生成(2020年4月10日 21:00:00) let date = calendar.date(from: DateComponents(year: 2020, month: 4, day: 10, hour: 21, minute: 0, second: 0)) |
Calendar.date()メソッドの引数fromには、DateComponents構造体を使って生成する日時の要素を指定します。
日時の加算/減算
Calendar構造体を使って日時の加算/減算を行う例です。
対象となる基準日時をDate構造体、加算する日時の要素はDateComponents構造体で示します。
DateComponentsの各要素をマイナス値にすると減算処理となります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/// 西暦(gregorian)カレンダーを生成 var calendar = Calendar(identifier: .gregorian) /// 基準の日時を生成(2020年4月10日 21:00:00) let baseDate = calendar.date(from: DateComponents(year: 2020, month: 4, day: 10, hour: 21, minute: 0, second: 0))! /// 基準日時の5時間30分後を算出(加算) let resultDate1 = calendar.date(byAdding: DateComponents(hour: 5, minute: 30), to: baseDate) // → 2020年4月11日 2:30:00 /// 基準日時の20日前を算出(減算) let resultDate2 = calendar.date(byAdding: DateComponents(day: -20), to: baseDate) // → 2020年3月21日 21:00:00 |
Calendar構造体の生成
Calendar構造体の生成時には、次のように適用するカレンダー(暦法)を指定する必要があります。
よほど特別な理由が無い限り西暦カレンダー(.gregorian)を指定しておけば問題無いでしょう。
1 2 3 4 |
/// 西暦(グレゴリオ暦)カレンダーの生成 let calendar = Calendar(identifier: .gregorian) |
適用カレンダーを変えるとどうなるのか?
適用するカレンダーを変えると、日付の扱いが変わります。
次のコードは、2種類のDate構造体を生成する例ですが、採用するカレンダーによって生成される日付が異なるのがわかります。
同じ2020年でも和暦の場合は令和2020年(=西暦4038年)と解釈されています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/// 日付の構成要素作成(2020年4月16日 12時0分0秒) let dateComponents = DateComponents(year: 2020, month: 4, day: 16, hour: 12, minute: 0, second: 0) /// 西暦カレンダーでDate構造体に変換 let calendar1 = Calendar(identifier: .gregorian) let date1 = calendar1.date(from: dateComponents) print(date1!) // 2020-04-16 03:00:00 +0000 /// 和暦カレンダーでDate構造体に変換(令和2020年と解釈される) let calendar2 = Calendar(identifier: .japanese) let date2 = calendar2.date(from: dateComponents) print(date2!) // 4038-04-16 03:00:00 +0000 |
利用可能なカレンダー
利用可能なカレンダーは以下の通りです。
Calendar.Identifier(enum型)で定義されています。
Identifier | カレンダー(暦法) |
---|---|
gregorian | グレゴリオ暦、西暦(ヨーロッパ、西半球などの一般的なカレンダー) |
japanese | 和暦(元号を使った日本の暦法) |
iso8601 | ISO8601規格(日付と時刻に関するISO国際規格) |
hebrew | ユダヤ暦(ヘブライ暦) |
chinese | 中国暦(中国の旧暦) |
republicOfChina | 中華民国(台湾)で使われている暦法 |
buddhist | タイ仏暦(東南アジアの仏教徒の多い国などで用いらる) |
coptic | コプト暦(エジプトで用いられた太陽暦) |
ethiopicAmeteAlem | エチオピア暦(Amete Alem) |
ethiopicAmeteMihret | エチオピア暦(Amete Mihret) |
indian | インド暦(ヒンズー暦、インドの伝統的な暦法) |
islamic | イスラム暦(イスラム教社会で使われている暦法) |
islamicCivil | イスラム暦(常用) |
islamicTabular | イスラム暦(表計算) |
islamicUmmAlQura | ウンム・アルクラー暦(サウジアラビアの公式暦) |
persian | ペルシャ歴(イランを中心に中東で浸かられている暦法) |
iPhone端末でのカレンダー(暦法)設定
iPhone端末では「設定」>「一般 」>「言語と地域」 >「 暦法」で、確認・設定可能です。
手元のiPhoneで確認すると、西暦(グレゴリオ暦)、和暦、タイ仏暦 の3種しか選択できないようです。
なお、ここで設定したカレンダーは全てのアプリに適用されるわけではありません。
あくまで適用されるのはカレンダーの変更に対応しているアプリのみです。
端末のカレンダー情報を取得する
ユーザー端末のカレンダー情報は、次の方法で取得可能です。
アプリからは、情報の取得のみ可能で、端末のカレンダー情報の変更はできません。
1 2 3 4 5 |
/// 現在のカレンダー情報を取得 let calendar = Calendar.current print(calendar.identifire) // gregorian (current) |