DateはFoundationの構造体で、カレンダーやタイムゾーンに依存しない特定の時点を表します。この型は、2001年1月1日の基準日からの経過秒数を保存し、時間間隔の比較と計算のための基本的な操作を提供します。Apple Developer Documentation(2025)によると、DateはUIKitやSwiftUIからCloudKitやCore Dataまで、すべてのAppleフレームワークで使用されています。Dateの仕組みを理解することは、すべてのiOS開発者にとって不可欠であり、これなしでアプリケーションの時間を管理することは不可能です。
重要なポイント
DateはFoundationフレームワークの値型で、単一の絶対的な時点を取得します。カレンダー表現(年、月、日)とは異なり、Dateはタイムゾーンやカレンダーシステムに依存しません — 純粋に数値的なタイムスタンプ値です。
Dateの内部表現はTimeInterval(Doubleの型エイリアス)で、基準日(2001年1月1日 00:00:00 UTC)からの相対秒数を保存します。Appleは、iOSとmacOSが構築されたレガシーNeXTSTEPシステムとの互換性のために、Unix epoch(1970年)ではなくこの日付を選択しました。
DateはすべてのApple APIで標準の時間型として使用されています:UIDatePicker、DatePicker、UserDefaults、Codable、Core Data、CloudKit。Dateなしでは、スケジュール、タイマー、カレンダーイベント、データシリアライゼーション、および時間に関連するあらゆる操作を扱うことは不可能です。
Dateは、人間が読み取れる値ではなく物理的なタイムスタンプを表すという点でカレンダー型とは異なります。同じDateでも、異なるタイムゾーンでは異なるカレンダー日付に対応する可能性があります。コンポーネント(年、月、日)を抽出するには、CalendarとDateComponentsを介してDateを変換します。
Dateは、Grand Central Dispatchでのタスクディスパッチに使用されるDispatchTimeとも異なります。DispatchTimeはシステム起動時間に相対的ですが、Dateは保存、送信、復元が可能な絶対的なタイムスタンプです。
Date()は現在時刻のオブジェクトを作成する最も簡単な方法です。パラメータなしのイニシャライザは呼び出しの正確な時刻を返します。過去または未来の日付を作成するには、TimeIntervalとaddingTimeIntervalメソッド、または既存のDateからの初期化を使用します。
コンポーネントから任意の日付を作成するには、CalendarとDateComponentsのペアを使用します。Calendarは人間が読み取れるコンポーネント(年、月、日、時、分)をDateに変換します。ISO8601DateFormatterを介してISO 8601文字列から、またはDateFormatterを介して任意の文字列表現からDateを初期化することもできます。
Date.distantPastとDate.distantFutureは、過去と未来の無限に遠い瞬間を表す2つの静的プロパティです。これらはアルゴリズムでの日付のフィルタリングとソートのための境界値として使用されます。
import Foundation
// 現在時刻でDateを作成
let now = Date()
print("Current time: \(now)")
// 1時間後(3600秒)の日付
let inOneHour = now.addingTimeInterval(3600)
// コンポーネントから日付を作成
var components = DateComponents()
components.year = 2025
components.month = 12
components.day = 25
let christmas = Calendar.current.date(from: components)!
この例では、Dateを作成する3つの方法(現在時刻、間隔の追加、DateComponentsを介した作成)を示しています。3つのアプローチすべてが、ミリ秒精度のDate型の値を返します。Calendar.currentはユーザーのシステムカレンダーを使用します — Appleデバイスでは、これは通常グレゴリオ暦です。
TimeIntervalは、2つの時点間の秒数を表すDoubleの型エイリアスです。TimeIntervalの精度はミリ秒の端数に達し、ほとんどの実用的なタスクに十分です。負のTimeIntervalは基準点より過去を示します。
Dateはすべての標準比較演算子をサポートしています:==、<、>、<=、>=。Swiftは内部のTimeInterval値を自動的に比較します。compareメソッドは、より明示的な比較のために.orderedSame、.orderedAscending、.orderedDescendingのオプションを持つComparisonResultを返します。
Date.distance(to:)は指定された日付までのTimeIntervalを返すメソッドです。ターゲットの日付が過去にある場合、結果は負になります。advanced(by:)は現在の日付に指定されたTimeIntervalを追加して新しい日付を作成します。これらのメソッドはStrideableプロトコルを実装しており、DateをRangeおよびClosedRangeで使用できます。
let start = Date()
let end = start.addingTimeInterval(86400)
// 演算子を使用した比較
if start < end {
print("start is earlier")
}
// 2つの日付間のTimeInterval
let interval: TimeInterval = end.timeIntervalSince(start)
print("Seconds: \(Int(interval / 60)) minutes")
// 範囲内でDateを使用
let range = start...end
let mid = start.addingTimeInterval(43200)
if range.contains(mid) {
print("mid is between start and end")
}
86400のTimeIntervalは1日に対応します。より複雑な間隔(週、月、年)には、CalendarとDateComponentsを使用してください。これらの単位は可変長(うるう年、夏時間)であるためです。TimeIntervalは秒単位の固定間隔にのみ適用されます。
CalendarはDateと人間が読み取れるコンポーネントの間の橋渡し役です。Calendarはタイムゾーンとロケールを考慮して、DateをDateComponents(年、月、日、時、分、秒)に変換します。Calendarなしでは、Dateから年や月を抽出することは不可能です — Dateはその絶対的な性質のため、この情報を含んでいません。
Calendar.componentメソッドはDateから単一のコンポーネント(年、月、日、時、分、秒、曜日、四半期)を抽出します。Calendar.dateComponentsメソッドは1回の呼び出しでコンポーネントのセットを抽出します — これは各フィールドごとに個別にcomponentを呼び出すよりも効率的です。
Calendar.isDateInToday、isDateInTomorrow、isDateInYesterdayは相対的な日付を確認するための便利なメソッドです。Calendar.dateIntervalは指定された期間(日、週、月、年)の開始と終了を返します。Calendar.compareは指定されたコンポーネントまでの精度で日付を比較します — 例えば、月と日を考慮せずに年のみで比較します。
let calendar = Calendar.current
// コンポーネントの抽出
let year = calendar.component(.year, from: Date())
let month = calendar.component(.month, from: Date())
// 相対日付の確認
if calendar.isDateInToday(someDate) {
print("Today!")
}
// 日の開始と終了
let dayInterval = calendar.dateInterval(of: .day, for: Date())!
print("Day start: \(dayInterval.start)")
print("Day end: \(dayInterval.end)")
Calendar.currentはユーザーのシステム設定(カレンダー、タイムゾーン、ロケール)を使用します。テストや特定の計算のために、Calendar(identifier: .gregorian)を介して特定のパラメータでCalendarを作成し、timeZoneプロパティを介して目的のTimeZoneを設定できます。
DateFormatterは、Dateをユーザーに表示する必要がある場合の必須コンポーネントです。DateFormatterは指定された形式とロケールに従ってDateを文字列に変換します。String(describing:)を介してDateを直接文字列に変換すると、基準日とTimeIntervalを含む技術的な表現が返されます — これはユーザー向けではありません。
基本的なアプローチは、プリセットスタイルdateStyleとtimeStyleを使用することです。iOSは4つのスタイル(.short、.medium、.long、.full)をサポートしています。日付と時刻のスタイルを組み合わせることで、柔軟な表示設定が可能になります。DateFormatterは自動的にローカライゼーションを適用します:ロシア語ロケールの場合、日付は“2026年7月21日”の形式で表示されます。
ISO8601DateFormatterはISO 8601用の特殊なフォーマッタで、APIとデータ交換で最も一般的な形式です。このフォーマッタはDateFormatterよりも高速に動作し、ロケールに依存しないため、JSONでの日付のシリアライズに適しています。
// プリセットスタイル
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .short
let userString = formatter.string(from: Date())
// API用のISO 8601
let isoFormatter = ISO8601DateFormatter()
let apiString = isoFormatter.string(from: Date())
// 文字列からの解析
let parsed = isoFormatter.date(from: "2026-07-21T10:30:00Z")!
DateFormatterを使用する際は、パフォーマンスを覚えておくことが重要です:新しいフォーマッタの作成は高コストな操作です。フォーマッタをキャッシュするか、一度作成して再利用することをお勧めします。フォーマッタのプロパティでtimeZoneを設定できます — デフォルトではシステムのタイムゾーンが使用されますが、サーバー日付の場合はTimeZone(identifier: “UTC”)がしばしば必要です。
iOSアプリケーションでのDateを使用した典型的なシナリオを見てみましょう。最初のシナリオは、ユーザーの生年月日からの年齢計算です。2つ目はイベントまでのカウントダウンタイマーです。3つ目はテーブルセクションとして表示するための日付によるレコードのグループ化です。
Calendar.dateComponentsを[.year]フラグとともに使用すると、2つの日付の差を計算します。正しいタイムゾーンの設定は重要です — CalendarでtimeZoneを指定しないと、別のタイムゾーンで真夜中を越えるために結果が1日異なる可能性があります。
func calculateAge(from birthDate: Date) -> Int {
let calendar = Calendar.current
let now = Date()
let components = calendar.dateComponents(
[.year], from: birthDate, to: now
)
return components.year ?? 0
}
カウントダウンタイマーはTimeIntervalを使用して実装されます。ターゲット日付と現在の日付の差を計算し、秒単位の残りを取得して日、時、分に変換します。定期的な更新には、1秒間隔のTimerを使用します。@Publishedプロパティを持つObservableObjectにより、SwiftUIは自動的にインターフェースを更新できます。
日付によるグループ化は、Dateをキーとして辞書を使用して実装されます。Calendar.dateInterval(of: .day, for:)は日付を日の開始に正規化し、同じ日に属するレコードをグループ化できます。同じアプローチは週、月、年でも機能します — dateIntervalのコンポーネントを.weekOfYearや.monthに変更するだけです。
| シナリオ | 主要API | 注意点 |
|---|---|---|
| 年齢計算 | Calendar.dateComponents | timeZoneを考慮 |
| カウントダウン | Date.timeIntervalSince | Timer+Combine |
| 日付グループ化 | Calendar.dateInterval | 日単位に正規化 |
| JSONシリアライズ | ISO8601DateFormatter | Localeは影響なし |
よくある質問
Dateはカレンダーやロケールに依存しない時間の内部表現です。文字列はユーザー設定に依存するフォーマットされた表示です。Dateは100%の精度で比較、シリアライズ、数学的処理が可能ですが、文字列表現は常にフォーマッタを介した解析が必要です。
Dateはタイムゾーンに依存しない絶対的なタイムスタンプ(基準日からの秒数)です。タイムゾーンは表示コンテキストです。UTCとモスクワの同じDateは同じ物理的な瞬間を表しますが、異なるカレンダー時間として表示されます。
DateはCore Dataで属性型としてネイティブにサポートされています。Core Dataは自動的にDateをストレージにシリアライズします。日付フィルタリングを使用したクエリには、比較演算子とともにNSPredicateを使用してください — Core DataはSQLiteレベルでタイムゾーンを正しく処理します。
CFAbsoluteTimeは同じ基準日(2001年1月1日)を使用するCore Foundation型です。DateとCFAbsoluteTimeは直接変換によって相互に交換可能です。Date(timeIntervalSinceReferenceDate:)はCFAbsoluteTimeを受け入れ、Date.timeIntervalSinceReferenceDateはCFAbsoluteTimeを返します。
Dateはミリ秒精度を持ちますが、iOS/macOSのハードウェア制限によりナノ秒精度は保証されません。高精度測定には、ハードウェアプロセッササイクルカウンタで動作するmach_absolute_timeまたはSwift 5.7+のContinuousClockを使用してください。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。