Dateとは何か、Foundationにおける時間型とTimeInterval

著者: IT Sectr 公開日: 2026-07-12 読了時間: 7 分

DateはFoundationの構造体で、カレンダーやタイムゾーンに依存しない特定の時点を表します。この型は、2001年1月1日の基準日からの経過秒数を保存し、時間間隔の比較と計算のための基本的な操作を提供します。Apple Developer Documentation(2025)によると、DateはUIKitやSwiftUIからCloudKitやCore Dataまで、すべてのAppleフレームワークで使用されています。Dateの仕組みを理解することは、すべてのiOS開発者にとって不可欠であり、これなしでアプリケーションの時間を管理することは不可能です。

重要なポイント

  • Date — 基準日からの秒数として絶対的な時点を保存するFoundation構造体。
  • TimeInterval — 2つの時点間の間隔を秒単位で表すDouble型。
  • Date() — 呼び出し時の現在時刻でオブジェクトを作成するイニシャライザ。
  • 日付の比較は比較演算子またはcompare、earlierDate、laterDateメソッドを使用して行われます。
  • DateFormatter — ユーザーに日付を読み取り可能な形式で表示するための必須コンポーネント。

FoundationにおけるDateとは?

DateはFoundationフレームワークの値型で、単一の絶対的な時点を取得します。カレンダー表現(年、月、日)とは異なり、Dateはタイムゾーンやカレンダーシステムに依存しません — 純粋に数値的なタイムスタンプ値です。

Dateの内部表現はTimeInterval(Doubleの型エイリアス)で、基準日(2001年1月1日 00:00:00 UTC)からの相対秒数を保存します。Appleは、iOSとmacOSが構築されたレガシーNeXTSTEPシステムとの互換性のために、Unix epoch(1970年)ではなくこの日付を選択しました。

DateはすべてのApple APIで標準の時間型として使用されています:UIDatePickerDatePickerUserDefaultsCodableCore DataCloudKit。Dateなしでは、スケジュール、タイマー、カレンダーイベント、データシリアライゼーション、および時間に関連するあらゆる操作を扱うことは不可能です。

Dateと他の時間型の比較

Dateは、人間が読み取れる値ではなく物理的なタイムスタンプを表すという点でカレンダー型とは異なります。同じDateでも、異なるタイムゾーンでは異なるカレンダー日付に対応する可能性があります。コンポーネント(年、月、日)を抽出するには、CalendarDateComponentsを介してDateを変換します。

Dateは、Grand Central Dispatchでのタスクディスパッチに使用されるDispatchTimeとも異なります。DispatchTimeはシステム起動時間に相対的ですが、Dateは保存、送信、復元が可能な絶対的なタイムスタンプです。

SwiftでのDateの作成

Date()は現在時刻のオブジェクトを作成する最も簡単な方法です。パラメータなしのイニシャライザは呼び出しの正確な時刻を返します。過去または未来の日付を作成するには、TimeIntervalとaddingTimeIntervalメソッド、または既存のDateからの初期化を使用します。

コンポーネントから任意の日付を作成するには、CalendarDateComponentsのペアを使用します。Calendarは人間が読み取れるコンポーネント(年、月、日、時、分)をDateに変換します。ISO8601DateFormatterを介してISO 8601文字列から、またはDateFormatterを介して任意の文字列表現からDateを初期化することもできます。

Date.distantPastDate.distantFutureは、過去と未来の無限に遠い瞬間を表す2つの静的プロパティです。これらはアルゴリズムでの日付のフィルタリングとソートのための境界値として使用されます。

swift
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と日付の比較

TimeIntervalは、2つの時点間の秒数を表すDoubleの型エイリアスです。TimeIntervalの精度はミリ秒の端数に達し、ほとんどの実用的なタスクに十分です。負のTimeIntervalは基準点より過去を示します。

Dateはすべての標準比較演算子をサポートしています:==<><=>=。Swiftは内部のTimeInterval値を自動的に比較します。compareメソッドは、より明示的な比較のために.orderedSame、.orderedAscending、.orderedDescendingのオプションを持つComparisonResultを返します。

Date.distance(to:)は指定された日付までのTimeIntervalを返すメソッドです。ターゲットの日付が過去にある場合、結果は負になります。advanced(by:)は現在の日付に指定されたTimeIntervalを追加して新しい日付を作成します。これらのメソッドはStrideableプロトコルを実装しており、DateをRangeおよびClosedRangeで使用できます。

swift
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とDateComponents

CalendarはDateと人間が読み取れるコンポーネントの間の橋渡し役です。Calendarはタイムゾーンとロケールを考慮して、DateをDateComponents(年、月、日、時、分、秒)に変換します。Calendarなしでは、Dateから年や月を抽出することは不可能です — Dateはその絶対的な性質のため、この情報を含んでいません。

Calendar.componentメソッドはDateから単一のコンポーネント(年、月、日、時、分、秒、曜日、四半期)を抽出します。Calendar.dateComponentsメソッドは1回の呼び出しでコンポーネントのセットを抽出します — これは各フィールドごとに個別にcomponentを呼び出すよりも効率的です。

Calendar.isDateInTodayisDateInTomorrowisDateInYesterdayは相対的な日付を確認するための便利なメソッドです。Calendar.dateIntervalは指定された期間(日、週、月、年)の開始と終了を返します。Calendar.compareは指定されたコンポーネントまでの精度で日付を比較します — 例えば、月と日を考慮せずに年のみで比較します。

swift
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と日付の表示

DateFormatterは、Dateをユーザーに表示する必要がある場合の必須コンポーネントです。DateFormatterは指定された形式とロケールに従ってDateを文字列に変換します。String(describing:)を介してDateを直接文字列に変換すると、基準日とTimeIntervalを含む技術的な表現が返されます — これはユーザー向けではありません。

基本的なアプローチは、プリセットスタイルdateStyletimeStyleを使用することです。iOSは4つのスタイル(.short、.medium、.long、.full)をサポートしています。日付と時刻のスタイルを組み合わせることで、柔軟な表示設定が可能になります。DateFormatterは自動的にローカライゼーションを適用します:ロシア語ロケールの場合、日付は“2026年7月21日”の形式で表示されます。

ISO8601DateFormatterはISO 8601用の特殊なフォーマッタで、APIとデータ交換で最も一般的な形式です。このフォーマッタはDateFormatterよりも高速に動作し、ロケールに依存しないため、JSONでの日付のシリアライズに適しています。

swift
// プリセットスタイル
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”)がしばしば必要です。

Dateの使用例

iOSアプリケーションでのDateを使用した典型的なシナリオを見てみましょう。最初のシナリオは、ユーザーの生年月日からの年齢計算です。2つ目はイベントまでのカウントダウンタイマーです。3つ目はテーブルセクションとして表示するための日付によるレコードのグループ化です。

生年月日から年齢を計算する

Calendar.dateComponentsを[.year]フラグとともに使用すると、2つの日付の差を計算します。正しいタイムゾーンの設定は重要です — CalendarでtimeZoneを指定しないと、別のタイムゾーンで真夜中を越えるために結果が1日異なる可能性があります。

swift
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.dateComponentstimeZoneを考慮
カウントダウンDate.timeIntervalSinceTimer+Combine
日付グループ化Calendar.dateInterval日単位に正規化
JSONシリアライズISO8601DateFormatterLocaleは影響なし

よくある質問

Dateと日付文字列の違いは何ですか?

Dateはカレンダーやロケールに依存しない時間の内部表現です。文字列はユーザー設定に依存するフォーマットされた表示です。Dateは100%の精度で比較、シリアライズ、数学的処理が可能ですが、文字列表現は常にフォーマッタを介した解析が必要です。

Dateにタイムゾーン情報が含まれないのはなぜですか?

Dateはタイムゾーンに依存しない絶対的なタイムスタンプ(基準日からの秒数)です。タイムゾーンは表示コンテキストです。UTCとモスクワの同じDateは同じ物理的な瞬間を表しますが、異なるカレンダー時間として表示されます。

Core Dataで時間を保存するにはどの型を使用すべきですか?

DateはCore Dataで属性型としてネイティブにサポートされています。Core Dataは自動的にDateをストレージにシリアライズします。日付フィルタリングを使用したクエリには、比較演算子とともにNSPredicateを使用してください — Core DataはSQLiteレベルでタイムゾーンを正しく処理します。

DateとCFAbsoluteTimeの違いは何ですか?

CFAbsoluteTimeは同じ基準日(2001年1月1日)を使用するCore Foundation型です。DateとCFAbsoluteTimeは直接変換によって相互に交換可能です。Date(timeIntervalSinceReferenceDate:)はCFAbsoluteTimeを受け入れ、Date.timeIntervalSinceReferenceDateはCFAbsoluteTimeを返します。

Dateは高精度測定に使用できますか?

Dateはミリ秒精度を持ちますが、iOS/macOSのハードウェア制限によりナノ秒精度は保証されません。高精度測定には、ハードウェアプロセッササイクルカウンタで動作するmach_absolute_timeまたはSwift 5.7+のContinuousClockを使用してください。

まとめ

  • Date — 2001年1月1日の基準日からのTimeIntervalとして絶対的な時点を保存するFoundation値型。
  • TimeInterval(Double) — 2つの日付間の秒数で、Dateとの比較と算術を提供。
  • CalendarDateComponents — Dateから年、月、日、その他のカレンダーコンポーネントを抽出する唯一の方法。
  • DateFormatterISO8601DateFormatter — 文字列形式で日付を表示およびシリアライズするための必須ツール。
  • Date.distantPastDate.distantFuture — アルゴリズムでのフィルタリングとソートのための境界値。
  • Dateにタイムゾーンは含まれない — 表示用のコンポーネント抽出時にCalendarレベルでタイムゾーンが追加される。
  • Core DataとCodableはDateをネイティブにサポートし、追加の変換なしで日付の保存と転送を簡素化。

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください