【Swift】Date構造体の使い方!日付の計算や比較方法

この記事からわかること

  • SwiftDate構造体使い方
  • 日付差分加算減算などの計算方法
  • UTCによる9時間ズレ
  • 比較演算子を用いた比較

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

参考文献: API Collection Dates and Times

Swiftの日付や時間操作API

Swiftでは日付や時間などを操作、管理するためにいくつかの構造体やクラスが基礎となるFoundationフレークワークの中に用意されています。

Date構造体・・・日付(カレンダーやタイムゾーンと無関係)
DateInterval構造体・・・期間
TimeIntervalタイプエイリアス・・・秒数(Double型のエイリアス)
DateComponents構造体・・・日付(カレンダーやタイムゾーン)
Calendar構造体・・・カレンダー
TimeZone構造体・・・タイムゾーン
DateFormatterクラス・・・文字列表現など

ざっくり見ると上記の通りです。それぞれ日時に関する機能を提供するAPIですが細かい役割が異なります。

Date構造体とは?

Date構造体とは設定されているカレンダーやタイムゾーンとは関連を持たず、特定の日時を表現するオブジェクトです。引数なしのイニシャライザまたはタイププロパティ(static)nowから現在時刻のインスタンスを生成(参照)することができます。

おすすめ記事:【Swift】プロパティの種類!ストアドプロパティやタイププロパティとは?


let day = Date() // Feb 10, 2023 at 7:02 PM
print(day) // 2023-02-10 10:02:22 +0000


let day2 = Date.now // Feb 10, 2023 at 7:02 PM
print(day2) // 2023-02-10 10:02:22 +0000

9時間のズレが生じる原因

しかしprintした時刻とオブジェクトの時刻では10時とPM 7時(19時)日時情報には誤差が生まれています。これはDateオブジェクトがUTC(協定世界時)で日時情報を保持しているためであり、UTCと日本標準時(JTC)とは9時間ズレているため誤差が生まれてしまうのです。

playgroundで見た時に+0000となるのは誤差が0時間(つまりUTC)であることを表しています。

日本標準時で文字列として出力したい場合はdescription(with:)メソッドの引数に任意のロケール値を渡せば出力可能です。

print(day.description(with: Locale(identifier: "ja_JP")))
// 2023年2月10日 金曜日 19時06分57秒 日本標準時

またDateFormatterクラスを使用した方法でも出力できます。

let df = DateFormatter()
df.calendar = Calendar(identifier: .gregorian)
df.locale = Locale(identifier: "ja_JP")
df.timeZone = TimeZone(identifier: "Asia/Tokyo")
df.dateStyle = .full
df.timeStyle = .short
print(df.string(from: Date()))
// 2023年2月10日 金曜日 19:06

任意の時間後のオブジェクトを生成する

現在時刻のオブジェクトの生成方法が分かったところで30秒後や2日後、1年後など任意の時間経過後のオブジェクトを生成する方法をみていきます。

実装するにはinit(timeIntervalSinceNow:)を使用します。引数にはTimeInterval型(Doubleのエイリアス)で現在から任意の日時までの秒数を渡します。

// 30秒後の日時
let dayLater = Date(timeIntervalSinceNow: 30)
print(dayLater.description(with: Locale(identifier: "ja_JP")))
// 2023年2月10日 金曜日 19時09分56秒 日本標準時


// 明日(1日後)の日付 60秒 × 60分 × 24時間
let tomorrow = Date(timeIntervalSinceNow: ( 60 * 60 * 24))
print(tomorrow.description(with: Locale(identifier: "ja_JP")))
// 2023年2月11日 土曜日 19時09分26秒 日本標準時

// 1年後の日付 60秒 × 60分 × 24時間 × 365日
let yearLater = Date(timeIntervalSinceNow: ( 60 * 60 * 24 * 365))
print(yearLater.description(with: Locale(identifier: "ja_JP")))
// 2024年2月10日 土曜日 19時09分26秒 日本標準時

その他のプロパティやメソッド

struct Date {
    func compare(Date) -> ComparisonResult // 任意の日付とこの日付を比較
    func distance(to: Date) -> TimeInterval // この日付から任意の日付までの間隔
    func timeIntervalSince(Date) -> TimeInterval // この日付と任意の日付の間隔
    var timeIntervalSinceNow: TimeInterval // この日付と現在の日付と時刻の間隔
    func addTimeInterval(TimeInterval) // この日付に時間間隔を追加
    func addingTimeInterval(TimeInterval) -> Date // この日付に時間間隔を追加して、新しい日付値を作成
}

日付の比較

DateオブジェクトはComparableプロトコルに準拠しているため演算子(=><)を用いた比較が可能になっています。

let day1 = Date()
print(day1.description(with: Locale(identifier: "ja_JP")))
// 2023年2月10日 金曜日 19時16分13秒 日本標準時
let day2 = Date()
print(day2.description(with: Locale(identifier: "ja_JP")))
// 2023年2月10日 金曜日 19時16分13秒 日本標準時
if day1 == day2 {
  print("OK")
} else  {
  print("NG") // NG
}

上記の場合は一致になりそうですが、インスタンス化のタイミングにわずかながら誤差がある(秒数がズレる)ため不一致になるのでしょうか。もちろん同じインスタンス同士は一致し、比較してみるとday2の方が大きい(時間が進んでいる)となるようです。

if day1 == day1 {
  print("OK") // OK
} else  {
  print("NG")
}

if day1 < day2 {
  print("OK") // OK
} else  {
  print("NG")
}

おすすめ記事:【Swift】日付が期間内か識別する方法!switch文で範囲の定義

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

自作iOSアプリ

\ アプリをリリースしました /

mapping

自分だけの地図を作ろう!-mapping-

無料posted withアプリーチ

割り勘アプリ-bill-

旅行におすすめ!
割り勘アプリ-bill-

無料posted withアプリーチ

Imakoko

現在地を取得するアプリ!Imakoko

無料posted withアプリーチ

ふるログ

ふるさと納税管理アプリ-ふるログ-

無料posted withアプリーチ

Remind-シンプル通知アプリ-

シンプル通知アプリ-Remind-

無料posted withアプリーチ

CLIPURL

好きな記事をクリップしよう!-CLIPURL-

無料posted withアプリーチ

記録カレンダー

続けたを可視化できるアプリ!記録カレンダー

無料posted withアプリーチ

CART-共有できるお買い物リスト-

CART-共有できるお買い物リスト-

無料posted withアプリーチ

QuickPressPanel

早押しゲーム-QuickPressPanel-

無料posted withアプリーチ

貸し借り管理アプリ

友達とのお金の管理-貸し借り管理アプリ-

無料posted withアプリーチ

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

Githubにて
iOSアプリのソースコードを公開中!

自作Webアプリ

子育て知識共有サイト-mikata-

子育て知識共有サイト-mikata-

New Article

index