Date — е структура от Foundation, която представя конкретен момент от време, независимо от календара и часовата зона. Типът съхранява броя секунди, изминали от референтната дата 1 януари 2001 г. (reference date), и осигурява основни операции за сравнение и изчисляване на времеви интервали. Според Apple Developer Documentation (2025), Date се използва във всички рамки на Apple: от UIKit и SwiftUI до CloudKit и Core Data. Разбирането на работата на Date е задължително за всеки iOS разработчик, тъй като без него е невъзможно да се управлява времето в приложението.
Основни точки
Date — е тип стойност от рамката Foundation, който записва един абсолютен момент от време. За разлика от календарните представяния (година, месец, ден), Date не зависи от часовата зона и календарната система — това е чисто числова стойност на времеви печат.
Вътрешното представяне на Date е TimeInterval (псевдоним за Double), съхраняващ броя секунди спрямо референтната дата — 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")
// 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, равен на 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())
// Check relative 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, който използва същата референтна дата (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 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също