Date is a Foundation structure that represents a specific moment in time, independent of calendar and time zone. The type stores the number of seconds elapsed since the reference date of January 1, 2001, and provides basic operations for comparison and calculation of time intervals. According to Apple Developer Documentation (2025), Date is used in all Apple frameworks: from UIKit and SwiftUI to CloudKit and Core Data. Understanding how Date works is essential for any iOS developer, since it is impossible to manage time in an application without it.
Key Takeaways
Date is a value type from the Foundation framework that captures a single absolute moment in time. Unlike calendar representations (year, month, day), Date does not depend on time zone or calendar system — it is a purely numeric timestamp value.
The internal representation of Date is TimeInterval (a type alias for Double), storing the number of seconds relative to the reference date — January 1, 2001, 00:00:00 UTC. Apple chose this date rather than the Unix epoch (1970) for compatibility with legacy NeXTSTEP systems, on which iOS and macOS are built.
Date is used as the standard time type in all Apple APIs: UIDatePicker, DatePicker, UserDefaults, Codable, Core Data, CloudKit. Without Date, it is impossible to work with schedules, timers, calendar events, data serialization, and any time-related operations.
Date differs from calendar types in that it represents a physical time stamp rather than a human-readable value. The same Date can correspond to different calendar dates in different time zones. To extract components (year, month, day), Date is converted through Calendar and DateComponents.
Date also differs from DispatchTime, which is used for task dispatching in Grand Central Dispatch. DispatchTime is relative to the system boot time, while Date is an absolute timestamp that can be saved, transmitted, and restored.
Date() is the simplest way to create an object with the current moment in time. The parameterless initializer returns the exact time of the call. To create a date in the past or future, use TimeInterval and the addingTimeInterval method, or initialization from an existing Date.
To create an arbitrary date from components, use the Calendar and DateComponents pair. Calendar converts human-readable components (year, month, day, hour, minute) into Date. You can also initialize Date through ISO8601DateFormatter from an ISO 8601 string, or through DateFormatter from an arbitrary string representation.
Date.distantPast and Date.distantFuture are two static properties representing infinitely distant moments in the past and future. They are used as boundary values for filtering and sorting dates in algorithms.
import Foundation
// Creating Date with current time
let now = Date()
print("Current time: \(now)")
// Date in 1 hour (3600 seconds)
let inOneHour = now.addingTimeInterval(3600)
// Date from components
var components = DateComponents()
components.year = 2025
components.month = 12
components.day = 25
let christmas = Calendar.current.date(from: components)!
The example shows three ways to create a Date: current time, adding an interval, and creating via DateComponents. All three approaches return a value of type Date with millisecond precision. Calendar.current uses the user’s system calendar — on Apple devices, this is typically the Gregorian calendar.
TimeInterval is a type alias for Double representing the number of seconds between two moments in time. TimeInterval precision reaches fractions of a millisecond, which is sufficient for most practical tasks. A negative TimeInterval indicates the past relative to the reference point.
Date supports all standard comparison operators: ==, <, >, <=, >=. Swift automatically compares the internal TimeInterval values. The compare method returns ComparisonResult with .orderedSame, .orderedAscending, .orderedDescending options for more explicit comparison.
Date.distance(to:) is a method that returns the TimeInterval to the specified date. If the target date is in the past, the result is negative. advanced(by:) creates a new date by adding the specified TimeInterval to the current one. These methods implement the Strideable protocol, allowing Date to be used in Range and ClosedRange.
let start = Date()
let end = start.addingTimeInterval(86400)
// Comparison using operators
if start < end {
print("start is earlier")
}
// TimeInterval between two dates
let interval: TimeInterval = end.timeIntervalSince(start)
print("Seconds: \(Int(interval / 60)) minutes")
// Using Date in range
let range = start...end
let mid = start.addingTimeInterval(43200)
if range.contains(mid) {
print("mid is between start and end")
}
TimeInterval of 86400 corresponds to one day. For more complex intervals — weeks, months, years — use Calendar and DateComponents, since these units have variable length (leap years, daylight saving time). TimeInterval is only applicable for fixed intervals in seconds.
Calendar is the bridge between Date and human-readable components. Calendar converts Date into DateComponents (year, month, day, hour, minute, second) taking into account time zone and locale. Without Calendar, it is impossible to extract the year or month from Date — Date does not contain this information due to its absolute nature.
The Calendar.component method extracts a single component from Date: year, month, day, hour, minute, second, weekday, quarter. The Calendar.dateComponents method extracts a set of components in a single call — this is more efficient than calling component for each field separately.
Calendar.isDateInToday, isDateInTomorrow, isDateInYesterday are convenient methods for checking relative dates. Calendar.dateInterval returns the start and end of the specified period (day, week, month, year). Calendar.compare compares dates with precision up to the specified component — for example, year without considering month and day.
let calendar = Calendar.current
// Extracting components
let year = calendar.component(.year, from: Date())
let month = calendar.component(.month, from: Date())
// Check relative date
if calendar.isDateInToday(someDate) {
print("Today!")
}
// Start and end of day
let dayInterval = calendar.dateInterval(of: .day, for: Date())!
print("Day start: \(dayInterval.start)")
print("Day end: \(dayInterval.end)")
Calendar.current uses the user’s system settings — calendar, time zone, and locale. For testing or specific calculations, you can create a Calendar with specific parameters through Calendar(identifier: .gregorian) and set the desired TimeZone via the timeZone property.
DateFormatter is a required component if Date needs to be displayed to the user. DateFormatter converts Date into a string according to the specified format and locale. Directly converting Date to a string via String(describing:) returns a technical representation with the reference date and TimeInterval — it is not intended for users.
The basic approach is to use the preset dateStyle and timeStyle. iOS supports four styles: .short, .medium, .long, .full. The combination of date and time styles allows flexible display configuration. DateFormatter automatically applies localization: for the Russian locale, the date will be displayed in the format “July 21, 2026”.
ISO8601DateFormatter is a specialized formatter for ISO 8601, the most common format for API and data exchange. This formatter works faster than DateFormatter and does not depend on locale, making it preferable for serializing dates in JSON.
// Preset styles
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .short
let userString = formatter.string(from: Date())
// ISO 8601 for API
let isoFormatter = ISO8601DateFormatter()
let apiString = isoFormatter.string(from: Date())
// Parsing from string
let parsed = isoFormatter.date(from: "2026-07-21T10:30:00Z")!
When working with DateFormatter, it is important to remember performance: creating a new formatter is an expensive operation. It is recommended to cache the formatter or create it once and reuse it. The formatter’s properties allow setting timeZone — by default, the system time zone is used, but for server dates, TimeZone(identifier: “UTC”) is often required.
Let’s consider typical scenarios for working with Date in an iOS application. The first scenario is calculating age from a user’s birth date. The second is a countdown timer to an event. The third is grouping records by date for display as table sections.
Calendar.dateComponents with the [.year] flag calculates the difference between two dates. Setting the correct time zone is critical — if you do not specify timeZone in Calendar, the result may differ by a day due to crossing midnight in another time zone.
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
}
Countdown timer is implemented using TimeInterval. Calculate the difference between the target date and the current date, get the remainder in seconds, and convert to days, hours, minutes. For regular updates, use Timer with a 1-second interval. An ObservableObject with an @Published property allows SwiftUI to automatically update the interface.
Grouping by date is implemented using a dictionary with Date as the key. Calendar.dateInterval(of: .day, for:) normalizes the date to the start of the day, allowing you to group records belonging to the same day. The same approach works for weeks, months, and years — simply change the component in dateInterval to .weekOfYear or .month.
| Scenario | Key API | Notes |
|---|---|---|
| Age calculation | Calendar.dateComponents | Account for timeZone |
| Countdown | Date.timeIntervalSince | Timer+Combine |
| Date grouping | Calendar.dateInterval | Normalize to day |
| JSON serialization | ISO8601DateFormatter | Locale does not affect |
Frequently Asked Questions
Date is an internal representation of time without binding to calendar and locale. A string is a formatted display dependent on user settings. Date can be compared, serialized, and mathematically processed with 100% accuracy, while string representation always requires parsing through a formatter.
Date is an absolute time stamp (number of seconds from the reference date) that does not depend on time zone. Time zone is a display context. The same Date in UTC and in Moscow represents the same physical moment but displays as different calendar time.
Date is natively supported by Core Data as an attribute type. Core Data automatically serializes Date to storage. For queries with date filtering, use NSPredicate with comparison operators — Core Data correctly handles timezone at the SQLite level.
CFAbsoluteTime is a Core Foundation type that uses the same reference date (January 1, 2001). Date and CFAbsoluteTime are interchangeable through direct conversion. Date(timeIntervalSinceReferenceDate:) accepts CFAbsoluteTime, and Date.timeIntervalSinceReferenceDate returns CFAbsoluteTime.
Date has millisecond precision but does not guarantee nanosecond precision due to iOS/macOS hardware limitations. For high-precision measurements, use mach_absolute_time or ContinuousClock from Swift 5.7+, which work on hardware processor cycle counters.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also