Dates and Formatting
Prerequisites: Structs
Foundation represents a moment in time with Date, and uses Calendar
for anything involving days, months, and time zones.
Date
A Date is a single point in time, independent of time zones:
import Foundation
let now = Date()
let inOneHour = now.addingTimeInterval(3600)
print(inOneHour > now)
print(inOneHour.timeIntervalSince(now))
let epoch = Date(timeIntervalSince1970: 0)
print(ISO8601DateFormatter().string(from: epoch))
true
3600.0
1970-01-01T00:00:00Z
timeIntervalSince1970 is the Unix timestamp. The
Unix Epoch Converter translates these
back and forth.
Calendar arithmetic
Use Calendar rather than adding seconds, because days and months
aren't a fixed length (daylight saving, leap years):
import Foundation
var calendar = Calendar(identifier: .gregorian)
calendar.timeZone = TimeZone(identifier: "UTC")!
let start = calendar.date(from: DateComponents(year: 2025, month: 1, day: 31))!
let nextMonth = calendar.date(byAdding: .month, value: 1, to: start)!
let parts = calendar.dateComponents([.year, .month, .day], from: nextMonth)
print(parts.year!, parts.month!, parts.day!)
let end = calendar.date(from: DateComponents(year: 2025, month: 12, day: 25))!
print(calendar.dateComponents([.day], from: start, to: end).day!)
2025 2 28
328
Adding one month to 31 January gives 28 February — Calendar knows
February is shorter.
Formatting for people
Dates shown to users should follow their language and region:
let text = Date().formatted(date: .abbreviated, time: .shortened)
// e.g. "Jan 15, 2025 at 9:30 AM" in the US, "15 Jan 2025 at 09:30" in the UK
Numbers work the same way:
1234.5.formatted(.currency(code: "EUR")).
Common mistakes
- Formatting dates by hand with a fixed pattern for display. Use
formatted(...)so users see their own conventions. Fixed formats are for exchanging data — use ISO 8601 (ISO8601DateFormatter) there. - Adding
86400seconds for "one day". Usecalendar.date(byAdding:).