Date — це структура Foundation, що представляє конкретний момент часу незалежно від календаря та часового поясу. Тип зберігає кількість секунд, що минули з контрольної дати 1 січня 2001 року (reference date), і забезпечує базові операції порівняння та обчислення часових інтервалів. За даними Apple Developer Documentation (2025), Date використовується у всіх фреймворках Apple: від UIKit і SwiftUI до CloudKit і Core Data. Розуміння роботи Date є обов'язковим для будь-якого iOS-розробника, оскільки без нього неможливо керувати часом у додатку.
Головне
Date — це value-тип із фреймворку Foundation, який фіксує один абсолютний момент часу. На відміну від календарних представлень (рік, місяць, день), Date не залежить від часового поясу та календарної системи — це суто числове значення часової мітки.
Внутрішнє представлення Date — це TimeInterval (псевдонім для Double), що зберігає кількість секунд відносно reference date — 1 січня 2001 року 00:00:00 UTC. Apple обрала цю дату, а не Unix epoch (1970 рік), для сумісності зі старими системами NeXTSTEP, на основі яких побудовано iOS і macOS.
Date використовується як стандартний тип часу у всіх API Apple: UIDatePicker, DatePicker, UserDefaults, Codable, Core Data, CloudKit. Без Date неможливо працювати з розкладами, таймерами, подіями календаря, серіалізацією даних та будь-якими операціями, пов'язаними з часом.
Date відрізняється від календарних типів тим, що представляє фізичну мітку часу, а не людиночитабельне значення. Один і той самий Date може відповідати різним календарним датам у різних часових поясах. Для отримання компонентів (рік, місяць, день) Date перетворюється через Calendar і DateComponents.
Date також відрізняється від DispatchTime, який використовується для диспетчеризації завдань у Grand Central Dispatch. DispatchTime відносний до моменту запуску системи, тоді як Date — абсолютна мітка, яку можна зберігати, передавати та відновлювати.
Date() — це найпростіший спосіб створити об'єкт із поточним моментом часу. Ініціалізатор без аргументів повертає точний час виклику. Для створення дати в минулому чи майбутньому використовуються TimeInterval і метод addingTimeInterval, або ініціалізація від існуючого Date.
Для створення довільної дати з компонентів використовується зв'язка Calendar і DateComponents. Calendar перетворює людиночитабельні компоненти (рік, місяць, день, година, хвилина) у Date. Також можна ініціалізувати Date через ISO8601DateFormatter з рядка у форматі ISO 8601 або через DateFormatter з довільного рядкового представлення.
Date.distantPast і Date.distantFuture — дві статичні властивості, що представляють нескінченно віддалені моменти минулого та майбутнього. Вони використовуються як граничні значення при фільтрації та сортуванні дат в алгоритмах.
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: поточний час, додавання інтервалу та створення через DateComponents. Усі три підходи повертають значення типу Date з точністю до мілісекунди. Calendar.current використовує системний календар користувача — на пристроях Apple це зазвичай григоріанський календар.
TimeInterval — це псевдонім для Double, що представляє кількість секунд між двома моментами часу. Точність TimeInterval досягає часток мілісекунди, що достатньо для більшості прикладних завдань. Від'ємне значення TimeInterval вказує на минуле відносно точки відліку.
Date підтримує всі стандартні оператори порівняння: ==, <, >, <=, >=. Swift автоматично порівнює внутрішні TimeInterval значень. Метод compare повертає ComparisonResult з варіантами .orderedSame, .orderedAscending, .orderedDescending для більш явного порівняння.
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")
}
// 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")
}
TimeInterval у 86400 відповідає одній добі. Для більш складних інтервалів — тижнів, місяців, років — використовуйте Calendar і DateComponents, оскільки ці одиниці мають змінну довжину (високосні роки, перехід на літній час). TimeInterval застосовний лише для фіксованих проміжків у секундах.
Calendar — це міст між Date та людиночитабельними компонентами. Calendar перетворює Date у DateComponents (рік, місяць, день, година, хвилина, секунда) з урахуванням часового поясу та локалі. Без Calendar неможливо витягти з Date рік або місяць — Date не містить цієї інформації через свою абсолютну природу.
Метод Calendar.component витягує один компонент із Date: рік, місяць, день, година, хвилина, секунда, weekday, quarter. Метод Calendar.dateComponents витягує набір компонентів за один виклик — це ефективніше, ніж викликати 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 з конкретними параметрами через Calendar(identifier: .gregorian) і встановити потрібний TimeZone через властивість timeZone.
DateFormatter — обов'язковий компонент, якщо Date потрібно відобразити користувачеві. DateFormatter перетворює Date у рядок за заданим форматом і локаллю. Пряме перетворення Date у рядок через String(describing:) повертає технічне представлення з reference date та TimeInterval — воно не призначене для користувача.
Базовий підхід — використання попередньо встановлених стилів dateStyle і timeStyle. iOS підтримує чотири стилі: .short, .medium, .long, .full. Комбінація стилів дати та часу дозволяє гнучко налаштувати відображення. DateFormatter автоматично застосовує локалізацію: для української локалі дата відобразиться у форматі «21 липня 2026 р.».
ISO8601DateFormatter — спеціалізований форматер для ISO 8601, найбільш поширеного формату для API та обміну даними. Цей форматер працює швидше за DateFormatter і не залежить від локалі, що робить його кращим для серіалізації дат у JSON.
// Попередньо встановлені стилі
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .short
let userString = formatter.string(from: Date())
// ISO 8601 для API
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-додатку. Перший сценарій — розрахунок віку користувача з дати народження. Другий — таймер зворотного відліку до події. Третій — групування записів за датою для відображення у вигляді секцій таблиці.
Calendar.dateComponents з прапорцем [.year] обчислює різницю між двома датами. Встановлення правильного часового поясу критично важливе — якщо не вказати timeZone у Calendar, результат може відрізнятися на день через перехід через північ в іншому часовому поясі.
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. Обчислюємо різницю між цільовою датою та поточною, отримуємо залишок у секундах і перетворюємо в дні, години, хвилини. Для регулярного оновлення використовується Timer з інтервалом 1 секунда. ObservableObject із властивістю @Published дозволяє 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 можна порівнювати, серіалізувати та математично обробляти зі стовідсотковою точністю, рядкове представлення завжди вимагає парсингу через форматер.
Date — це абсолютна мітка часу (кількість секунд від reference date), яка не залежить від часового поясу. Часовий пояс — це контекст відображення. Той самий Date в UTC і в Києві представляє один і той самий фізичний момент, але відображається як різний календарний час.
Date безпосередньо підтримується Core Data як тип атрибута. Core Data автоматично серіалізує Date у сховищі. Для запитів із фільтрацією за датою використовуйте NSPredicate з операторами порівняння — Core Data коректно обробляє timezone на рівні SQLite.
CFAbsoluteTime — це Core Foundation тип, що використовує ту саму reference date (1 січня 2001). Date і CFAbsoluteTime взаємозамінні через пряме перетворення. Date(timeIntervalSinceReferenceDate:) приймає CFAbsoluteTime, і Date.timeIntervalSinceReferenceDate повертає CFAbsoluteTime.
Date має точність до мілісекунди, але не гарантує наносекундну точність через апаратні обмеження iOS/macOS. Для високоточних вимірювань використовуйте mach_absolute_time або ContinuousClock із Swift 5.7+, які працюють на апаратних лічильниках циклів процесора.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також