はじめに
前回の記事では、DateFormatter を使用して日付操作を行う Tips を紹介しました。
今回は Calendar を使用して、日付間の差や、時間の差を求める方法について説明します。
環境
Xcode: 10.2.1
Swift: 5.0.1
目次
- Calendar のインスタンス化
- 指定した日付間の日数差を求めるには?
- 指定した日付間の時間差を求めるには?
- 指定した日付間の分間差を求めるには?
- 指定した日付間の秒間差を求めるには?
- 1:00:15 のような書式で差を表すには?
Calendarのインスタンス化
はじめに、Calendar 構造体をインスタンス化する方法をおさえておきましょう。
Calendar 構造体をインスタンス化するには、以下の書式を使用します。
書式 |
let 変数 = Calendar(Identifier) |
引数の Identifier には、Identifier 列挙体の値を渡します。
Identifirer 列挙体には、様々な値があるのですが、
.gregorian を指定すると グレゴリオ暦(つまり西暦を表す現代のカレンダー)を使用することになります。グレコリオ歴については Wikipedia を参照してください。 https://ja.wikipedia.org/wiki/%E3%82%B0%E3%83%AC%E3%82%B4%E3%83%AA%E3%82%AA%E6%9A%A6
.japanese を指定すると 平成31年 や 令和元年 のように和暦を使用することになります。
指定した日付の日数差を求めるには?
2つの日付の差を求めるには dateComponents メソッドを使用します。
書式は以下の通りで、第3引数に指定した日付から第2引数の日付を引いて差が求められます。第1引数については後述します。
また、戻り値は DateComponets 型の値を返します。
書式 |
dateComponents(<components: Set<Calendar.Component>, |
第1引数には、Calendar.component 列挙体の値を指定します。
Calendar.components の代表的な値を以下表に示します。
Calendar.component 列挙体は、カレンダー日付のさまざまな構成要素を表す列挙体です。日付の差を取得したい場合は dateComponents メソッドの第1引数に「day」 を指定し、月の差を取得したい場合は「month」を指定します。
値 | 説明 |
era | 元号 |
year | 年 |
yearForWeekOfYear | 年の週 |
quarter | カレンダーの四半期 |
month | 月 |
weekOfYear | 年の週 |
weekOfMonth | 月の週 |
day | 日 |
hour | 時間 |
minute | 分 |
second | 秒 |
nanosecond | ナノ秒 |
calendar | カレンダー |
timeZone | タイムゾーン |
以下に日付間の差を求める例を示します。
import UIKit let cal = Calendar(identifier: .gregorian) // 現在日時を dt に代入 let dt1 = Date() // 3日後を求める(60秒 × 60分 × 24時間 × 3日) let dt2 = dt1.addingTimeInterval(60 * 60 * 24 * 3) // dt2 - dt1 を計算 let diff1 = cal.dateComponents([.day], from: dt1, to: dt2) // dt1 - dt2 を計算 let diff2 = cal.dateComponents([.day], from: dt2, to: dt1) print("差は \(diff1.day!) 日") print("差は \(diff2.day!) 日")
5行目で現在日時を取得し、7行目で現在日時から3日後を求めています。日付間の差を取得したいので、dateComponents の第1引数には [.day] を渡します。
10行目は 3日後から今日を引いていますので diff1 には 3 が代入されます。
12行目は、今日から3日後を引いていますので diff2 には -3 が代入されます。
求めた差を表示するときは、diff1.Day のように日を表すプロパティで値を取得します。diff1.day のデータ型は Optional<Int> です。
実行例を以下に示します。
指定した日付間の時間差を求めるには?
指定した日付間の時間差を求めるには dateComponents メソッドの第1引数に [.hour] を指定します。
以下に日付間の時間差を求める例を示します。
import UIKit let cal = Calendar(identifier: .gregorian) // 現在日時を dt に代入 let dt1 = Date() // 8時間後を求める(60秒 × 60分 × 8時間) let dt2 = dt1.addingTimeInterval(60 * 60 * 8) // dt2 - dt1 を計算 let diff1 = cal.dateComponents([.hour], from: dt1, to: dt2) // dt1 - dt2 を計算 let diff2 = cal.dateComponents([.hour], from: dt2, to: dt1) print("差は \(diff1.hour!) 時間") print("差は \(diff2.hour!) 時間")
求めた差を表示するときは、diff1.hour のように時間を表すプロパティで値を取得します。diff1.hour のデータ型は Optional です。
実行例を以下に示します。
指定した日付の分間差を求めるには?
指定した日付間の分間差を求めるには dateComponents メソッドの第1引数に [.minute] を指定します。
以下に例を示します。
戻り値の diff1.minute のデータ型は Optional です。
import UIKit let cal = Calendar(identifier: .gregorian) // 現在日時を dt に代入 let dt1 = Date() // 15分後を求める(60秒 × 15分) let dt2 = dt1.addingTimeInterval(60 * 15) // dt2 - dt1 を計算 let diff1 = cal.dateComponents([.minute], from: dt1, to: dt2) // dt1 - dt2 を計算 let diff2 = cal.dateComponents([.minute], from: dt2, to: dt1) print("差は \(diff1.minute!) 分") print("差は \(diff2.minute!) 分")
指定した日付の秒間差を求めるには?
指定した日付間の分間差を求めるには dateComponents メソッドの第1引数に [.second] を指定します。
以下に例を示します。
戻り値の diff1.second のデータ型は Optional です。
import UIKit let cal = Calendar(identifier: .gregorian) // 現在日時を dt に代入 let dt1 = Date() // 15秒後を求める let dt2 = dt1.addingTimeInterval(15) // dt2 - dt1 を計算 let diff1 = cal.dateComponents([.second], from: dt1, to: dt2) // dt1 - dt2 を計算 let diff2 = cal.dateComponents([.second], from: dt2, to: dt1) print("差は \(diff1.second!) 秒") print("差は \(diff2.second!) 秒")
dateComponets メソッドで差を求める時の注意事項
すでに説明した通り、dateComponents メソッドの戻り値のプロパティの、day、hour、minute、second などは戻り値が Optional<Int> 型です。
よって、差が1.5時間のような場合、切り捨てられて 1.0時間となってしまいます。
差を正確に求めたい場合は、一旦小さな単位(例えば 秒)で求めておくことをお勧めします。
例えば、差が1.5時間を求めたい場合は、単位を分にして求めておけば、90(分)という値が求められます。求めた値を 60(分)で割り算すれば、1.5(時間)を導き出すことができます。
以下に例を示します。
この例では dt1 で現在日時を取得して、 dt2 に dt1 の1.5時間後の値を代入しています。その後、dateComponents メソッドを使用して差を分で求めた後、12行目のように 60(分)で割って単位が「時」の値を求めています。
import UIKit let cal = Calendar(identifier: .gregorian) // 現在日時を dt に代入 let dt1 = Date() // 1.5時間後を求める(60秒 × 60分 × 1.5時間) let dt2 = dt1.addingTimeInterval(60 * 60 * 1.5) // dt2 - dt1 を計算 let diff1 = cal.dateComponents([.minute], from: dt1, to: dt2) let dtHour = Double(diff1.minute!) / 60.0 print("差は \(dtHour) 時間")
1:00:15 のような書式で差を表すには?
dateComponents メソッドを使用することで、日付間の差を求める方法がわかりました。
最後に、求めた差を 1:00:15 のような書式で表示する方法について説明します。
1:00:15 のような書式で表示したい(文字列を作成したい)場合は、DateComponentsFormatter クラスを使用します。
はじめに、使用例を示します。
import UIKit let cal = Calendar(identifier: .gregorian) // 現在日時を dt に代入 let dt1 = Date() // 1時間15秒後を求める(60秒 × 60分 × 1時間 + 15秒) let dt2 = dt1.addingTimeInterval(60 * 60 * 1 + 15) // dt2 - dt1 を計算 let diff1 = cal.dateComponents([.second], from: dt1, to: dt2) // 書式を設定する let formatter = DateComponentsFormatter() // 表示単位を指定 formatter.unitsStyle = .positional // 表示する時間単位を指定 formatter.allowedUnits = [.hour, .minute, .second] // 設定した書式にしたがって表示 print(formatter.string(from: diff1)!)
時間の差を求めるコード(1〜10行目)までは、これまでに説明した内容と変わりありません。この例では、dt1 と dt2 に1時間15秒の差があります。
次に13行目以降で DateComponentsFormatter を使用して、1:00:15 と表示できるように書式.を設定しています。
1:00:15 のように表示できるような書式は、15行目の unitStyle プロパティを設定します。設定できる値については後述します。
続いて、求めておいた時間の差のうち、時、分、秒、のどれを表示するのかを配列で指定します。15行目は時、分、秒の全てを表示できるように [.hour, .minute, .second]を指定しています。
最後に(20行目) 文字列で表示するために、stringメソッドの引数に求めておいた DateComponents の値を渡します。
実行結果を以下に示します。
DateComponentsFormatter の unitStyle プロパティに指定可能な値と表示例を以下に示します。
値 | 表示例 |
positional | 1:00:15 |
abbreviated | 1h 15s |
brief | 1hr 15sec |
full | 1 hour, 15 seconds |
short | 1 hr, 15 sec |
spellOut | one hour, fifteen seconds |
コメント