うう、何回目だろう。気にしているつもりなんだけどなぁー。
参考になる人がいるかもなので、共有しますっ
1. ○分後 を取得する
たとえば、30分後を取得したいとき。
let date = dateGMT(year: 2018, month: 11, day: 4, hour: 8, minute: 30)
print("日付:", date)
let cal = Calendar(identifier: .gregorian)
var comps = cal.dateComponents([.year, .month, .day, .hour, .minute], from: date)
comps.minute! += 30
print("30分後", cal.date(from: comps)!)
とかくと、
日付: 2018-11-04 08:30:00 +0000
30分後 2018-11-04 09:00:00 +0000
...となりますが、iPhoneのTime Zoneをサンフランシスコにしていると、
日付: 2018-11-04 08:30:00 +0000
30分後 2018-11-04 10:00:00 +0000
になります。
2018-11-04 2:00:00 PDT = 2018-11-04 09:00:00 GMT がサマータイム終了タイミングで、1時間進むためです。
○分後 という絶対秒数を追加するには、素直にdate.addingTimeInterval(1800) と書けっつーことですな。
※ PDT = Pacific Daylight Time = 太平洋 サマータイム時間 UTC-7
PST = Pacific Standard Time = 太平洋 標準時間 UTC-8
2. カレンダーイベントの登録
カレンダー(EventKit)で、イベント(EKEvent)を登録する際、開始日時と終了日時でサマータイムの有無が変わる場合、注意が必要です。
たとえば、以下の日付のイベントを登録した場合。
開始日時: 2018-11-04 1:30:00 PDT = 2018-11-04 08:30:00 +0000
終了日時: 2018-11-04 1:00:00 PST = 2018-11-04 09:00:00 +0000
let event = EKEvent(eventStore: eventStore)
event.calendar = eventCalendar
event.title = "Test"
event.startDate = dateGMT(year: 2018, month: 11, day: 4, hour: 8, minute: 30)
event.endDate = dateGMT(year: 2018, month: 11, day: 4, hour: 9, minute: 00)
do {
try eventStore.save(event, span: .thisEvent)
} catch {
print(error)
}
iPhone端末のTime Zoneがサンフランシスコなど(US/Pacific)に設定されていると、以下の日付になってしまいます。
開始日時: 2018-11-04 1:30:00 PDT = 2018-11-04 08:30:00 +0000
終了日時: 2018-11-04 1:00:00 PDT = 2018-11-04 08:00:00 +0000
つまり開始が終了よりも遅い時間に。
ちゃんとDate型で指定しているのだから反応してよーーとは思うんですけどねぇw
ちなみに、iCloudのカレンダーで上記の状態になります。
同期しているGoogleカレンダーに登録すると、終了時刻が勝手に2時間後に置き換わるようです。
開始 > 終了 というのが不正な状態なので、その場合は置き換わるようになっていそう。
開始と終了日付のTime Zoneが別々に指定できたらよいのですが、iPhoneカレンダーは1つのTime Zone (サマータイム有無は現在の日時のものが有効?)の設定のみ。
Googleカレンダーは別々にTime Zoneが設定できるものの、サマータイム有無について設定ができるわけではない。
EKEventのtimeZoneプロパティに TimeZone(secondsFromGMT: 0) を設定すると正しい日時が登録ができます。
が、Googleカレンダーの場合、詳細を見るとGMTでの登録なのがわかる。
どうするのが一番良い方法なのかは分からず。
iPhoneの設定 > カレンダーにある、「Time Zone Override」の設定によっても変わる予感も。
ふむー。