[Tips] Calendar を使用して日付の差や時間の差を求めるには?

スポンサーリンク
Swift5

はじめに

前回の記事では、DateFormatter を使用して日付操作を行う Tips を紹介しました。

今回は Calendar を使用して、日付間の差や、時間の差を求める方法について説明します。

スポンサーリンク

環境

Xcode: 10.2.1

Swift: 5.0.1

スポンサーリンク

目次

スポンサーリンク

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>,
from: Date, to: Date) -> DateComponents

第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

 

コメント

タイトルとURLをコピーしました