Date: co to jest, typ czasu i TimeInterval w Foundation

Autor: IT Sectr Opublikowano: 2026-07-12 Czas czytania: 7 min

Date — to struktura Foundation reprezentująca konkretny moment czasu niezależnie od kalendarza i strefy czasowej. Typ przechowuje liczbę sekund, które upłynęły od daty referencyjnej 1 stycznia 2001 roku (reference date) i zapewnia podstawowe operacje porównywania oraz obliczania interwałów czasowych. Według Apple Developer Documentation (2025), Date jest używany we wszystkich frameworkach Apple: od UIKit i SwiftUI po CloudKit i Core Data. Zrozumienie działania Date jest niezbędne dla każdego programisty iOS, ponieważ bez niego nie można zarządzać czasem w aplikacji.

Najważniejsze

  • Date — struktura Foundation przechowująca absolutny moment czasu jako liczbę sekund od reference date.
  • TimeInterval — typ Double do reprezentacji interwału między dwoma momentami czasu w sekundach.
  • Date() — inicjalizator tworzący obiekt z bieżącym momentem czasu w momencie wywołania.
  • Porównywanie dat wykonuje się przez operatory porównania lub metody compare, earlierDate, laterDate.
  • DateFormatter — niezbędny komponent do wyświetlania daty użytkownikowi w czytelnym formacie.

Czym jest Date w Foundation?

Date — to typ wartościowy z frameworka Foundation, który rejestruje jeden absolutny moment czasu. W przeciwieństwie do reprezentacji kalendarzowych (rok, miesiąc, dzień), Date nie zależy od strefy czasowej ani systemu kalendarza — to czysto numeryczna wartość znacznika czasu.

Wewnętrzna reprezentacja Date to TimeInterval (alias dla Double), przechowujący liczbę sekund względem reference date — 1 stycznia 2001 roku 00:00:00 UTC. Apple wybrało tę datę, a nie Unix epoch (1970 rok), dla kompatybilności ze starymi systemami NeXTSTEP, na których oparte są iOS i macOS.

Date jest używany jako standardowy typ czasu we wszystkich API Apple: UIDatePicker, DatePicker, UserDefaults, Codable, Core Data, CloudKit. Bez Date nie można pracować z harmonogramami, timerami, wydarzeniami kalendarza, serializacją danych i wszelkimi operacjami związanymi z czasem.

Date vs inne typy czasu

Date różni się od typów kalendarzowych tym, że reprezentuje fizyczny znacznik czasu, a nie wartość czytelną dla człowieka. Ten sam Date może odpowiadać różnym datom kalendarzowym w różnych strefach czasowych. Aby uzyskać komponenty (rok, miesiąc, dzień), Date jest przekształcany przez Calendar i DateComponents.

Date różni się również od DispatchTime, który jest używany do dyspozytorii zadań w Grand Central Dispatch. DispatchTime jest względny względem momentu uruchomienia systemu, podczas gdy Date to absolutny znacznik, który można zapisywać, przesyłać i odtwarzać.

Tworzenie Date w Swift

Date() — to najprostszy sposób na utworzenie obiektu z bieżącym momentem czasu. Inicjalizator bez argumentów zwraca dokładny czas wywołania. Aby utworzyć datę w przeszłości lub przyszłości, używa się TimeInterval i metody addingTimeInterval albo inicjalizacji z istniejącego Date.

Do utworzenia dowolnej daty z komponentów używa się pary Calendar i DateComponents. Calendar przekształca czytelne dla człowieka komponenty (rok, miesiąc, dzień, godzina, minuta) na Date. Można również zainicjalizować Date przez ISO8601DateFormatter z ciągu znaków w formacie ISO 8601 lub przez DateFormatter z dowolnej reprezentacji tekstowej.

Date.distantPast i Date.distantFuture — dwie statyczne właściwości reprezentujące nieskończenie odległe momenty przeszłości i przyszłości. Są używane jako wartości graniczne przy filtrowaniu i sortowaniu dat w algorytmach.

swift
import Foundation

// Tworzenie Date z bieżącym czasem
let now = Date()
print("Current time: \(now)")

// Data za 1 godzinę (3600 sekund)
let inOneHour = now.addingTimeInterval(3600)

// Data z komponentów
var components = DateComponents()
components.year = 2025
components.month = 12
components.day = 25
let christmas = Calendar.current.date(from: components)!

W przykładzie pokazano trzy sposoby tworzenia Date: bieżący czas, dodanie interwału i tworzenie przez DateComponents. Wszystkie trzy podejścia zwracają wartość typu Date z dokładnością do milisekundy. Calendar.current używa systemowego kalendarza użytkownika — na urządzeniach Apple jest to zazwyczaj kalendarz gregoriański.

TimeInterval i porównywanie dat

TimeInterval — to alias dla Double, reprezentujący liczbę sekund między dwoma momentami czasu. Dokładność TimeInterval sięga ułamków milisekundy, co jest wystarczające dla większości zadań aplikacyjnych. Ujemna wartość TimeInterval wskazuje na przeszłość względem punktu odniesienia.

Date obsługuje wszystkie standardowe operatory porównania: ==, <, >, <=, >=. Swift automatycznie porównuje wewnętrzne TimeInterval wartości. Metoda compare zwraca ComparisonResult z wariantami .orderedSame, .orderedAscending, .orderedDescending dla bardziej jawnego porównania.

Date.distance(to:) — metoda zwracająca TimeInterval do wskazanej daty. Jeśli docelowa data jest w przeszłości, wynik jest ujemny. advanced(by:) tworzy nową datę, dodając podany TimeInterval do bieżącej. Te metody implementują protokół Strideable, umożliwiając użycie Date w zakresach Range i ClosedRange.

swift
let start = Date()
let end = start.addingTimeInterval(86400)

// Porównanie przez operatory
if start < end {
    print("start is earlier")
}

// TimeInterval między dwiema datami
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 równy 86400 odpowiada jednej dobie. W przypadku bardziej złożonych interwałów — tygodni, miesięcy, lat — używaj Calendar i DateComponents, ponieważ te jednostki mają zmienną długość (lata przestępne, zmiana czasu na letni). TimeInterval ma zastosowanie tylko dla stałych odstępów w sekundach.

Calendar i DateComponents

Calendar — to pomost między Date a czytelnymi dla człowieka komponentami. Calendar przekształca Date w DateComponents (rok, miesiąc, dzień, godzina, minuta, sekunda) z uwzględnieniem strefy czasowej i lokalizacji. Bez Calendar nie można wydobyć z Date roku ani miesiąca — Date nie zawiera tych informacji ze względu na swoją absolutną naturę.

Metoda Calendar.component wydobywa jeden komponent z Date: rok, miesiąc, dzień, godzina, minuta, sekunda, weekday, quarter. Metoda Calendar.dateComponents wydobywa zestaw komponentów w jednym wywołaniu — to bardziej efektywne niż wywoływanie component dla każdego pola osobno.

Calendar.isDateInToday, isDateInTomorrow, isDateInYesterday — wygodne metody sprawdzania dat względnych. Calendar.dateInterval zwraca początek i koniec wskazanego okresu (dzień, tydzień, miesiąc, rok). Calendar.compare porównuje daty z dokładnością do wskazanego komponentu — na przykład rok bez uwzględnienia miesiąca i dnia.

swift
let calendar = Calendar.current

// Wyodrębnianie komponentów
let year = calendar.component(.year, from: Date())
let month = calendar.component(.month, from: Date())

// Check relative date
if calendar.isDateInToday(someDate) {
    print("Today!")
}

// Początek i koniec dnia
let dayInterval = calendar.dateInterval(of: .day, for: Date())!
print("Day start: \(dayInterval.start)")
print("Day end: \(dayInterval.end)")

Calendar.current używa systemowych ustawień użytkownika — kalendarza, strefy czasowej i lokalizacji. Do testowania lub specyficznych obliczeń można utworzyć Calendar z konkretnymi parametrami przez Calendar(identifier: .gregorian) i ustawić odpowiednią TimeZone przez właściwość timeZone.

DateFormatter i wyświetlanie daty

DateFormatter — niezbędny komponent, jeśli Date ma być wyświetlony użytkownikowi. DateFormatter przekształca Date w ciąg znaków według podanego formatu i lokalizacji. Bezpośrednie przekształcenie Date na ciąg znaków przez String(describing:) zwraca techniczną reprezentację z reference date i TimeInterval — nie jest przeznaczona dla użytkownika.

Podstawowym podejściem jest użycie predefiniowanych stylów dateStyle i timeStyle. iOS obsługuje cztery style: .short, .medium, .long, .full. Kombinacja stylów daty i czasu pozwala elastycznie dostosować wyświetlanie. DateFormatter automatycznie stosuje lokalizację: dla polskiej lokalizacji data wyświetli się w formacie \"21 lipca 2026\".

ISO8601DateFormatter — wyspecjalizowany formatter dla ISO 8601, najczęściej spotykanego formatu dla API i wymiany danych. Ten formatter działa szybciej niż DateFormatter i nie zależy od lokalizacji, co czyni go preferowanym do serializacji dat w JSON.

swift
// Gotowe style
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .short
let userString = formatter.string(from: Date())

// ISO 8601 dla API
let isoFormatter = ISO8601DateFormatter()
let apiString = isoFormatter.string(from: Date())

// Parsowanie z ciągu znaków
let parsed = isoFormatter.date(from: "2026-07-21T10:30:00Z")!

Podczas pracy z DateFormatter należy pamiętać o wydajności: tworzenie nowego formattera to kosztowna operacja. Zaleca się cachowanie formattera lub utworzenie go raz i wielokrotne używanie. We właściwościach formattera można ustawić timeZone — domyślnie używana jest systemowa strefa czasowa, ale dla dat serwerowych często wymagany jest TimeZone(identifier: \"UTC\").

Przykłady użycia Date

Rozważmy typowe scenariusze pracy z Date w aplikacji iOS. Pierwszy scenariusz — obliczanie wieku użytkownika z daty urodzenia. Drugi — licznik czasu wstecz do wydarzenia. Trzeci — grupowanie wpisów według daty do wyświetlania w postaci sekcji tabeli.

Obliczanie wieku z daty urodzenia

Calendar.dateComponents z flagą [.year] oblicza różnicę między dwiema datami. Ustawienie prawidłowej strefy czasowej jest krytyczne — jeśli nie określisz timeZone w Calendar, wynik może różnić się o dzień z powodu przejścia przez północ w innej strefie czasowej.

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
}

Licznik czasu wstecz realizuje się przez TimeInterval. Obliczamy różnicę między datą docelową a bieżącą, otrzymujemy resztę w sekundach i przekształcamy na dni, godziny, minuty. Do regularnej aktualizacji używa się Timer z interwałem 1 sekundy. ObservableObject z właściwością @Published pozwala SwiftUI automatycznie aktualizować interfejs.

Grupowanie według daty realizuje się przez słownik z kluczem Date. Calendar.dateInterval(of: .day, for:) normalizuje datę do początku dnia, co pozwala zgrupować wpisy dotyczące tego samego dnia. To samo podejście działa dla tygodni, miesięcy i lat — wystarczy zmienić komponent w dateInterval na .weekOfYear lub .month.

ScenariuszKluczowe APICecha
Obliczanie wiekuCalendar.dateComponentsUwzględnić timeZone
Licznik wsteczDate.timeIntervalSinceTimer+Combine
Grupowanie datCalendar.dateIntervalNormalizacja do dnia
Serializacja JSONISO8601DateFormatterLocale nie wpływa

Często zadawane pytania

Czym Date różni się od ciągu znaków daty?

Date — to wewnętrzna reprezentacja czasu bez powiązania z kalendarzem i lokalizacją. Ciąg znaków to sformatowany widok zależny od ustawień użytkownika. Date można porównywać, serializować i matematycznie przetwarzać ze stuprocentową dokładnością, natomiast reprezentacja tekstowa zawsze wymaga parsowania przez formatter.

Dlaczego Date nie zawiera informacji o strefie czasowej?

Date — to absolutny znacznik czasu (liczba sekund od reference date), który nie zależy od strefy czasowej. Strefa czasowa to kontekst wyświetlania. Ten sam Date w UTC i w Warszawie reprezentuje ten sam fizyczny moment, ale wyświetla się jako różny czas kalendarzowy.

Jaki typ użyć do przechowywania czasu w Core Data?

Date jest bezpośrednio obsługiwany przez Core Data jako typ atrybutu. Core Data automatycznie serializuje Date w magazynie. Do zapytań z filtrowaniem według daty używaj NSPredicate z operatorami porównania — Core Data poprawnie obsługuje timezone na poziomie SQLite.

Jaka jest różnica między Date a CFAbsoluteTime?

CFAbsoluteTime — to typ Core Foundation używający tej samej reference date (1 stycznia 2001). Date i CFAbsoluteTime są wzajemnie wymienne przez bezpośrednią konwersję. Date(timeIntervalSinceReferenceDate:) przyjmuje CFAbsoluteTime, a Date.timeIntervalSinceReferenceDate zwraca CFAbsoluteTime.

Czy można używać Date do precyzyjnych pomiarów?

Date ma dokładność do milisekundy, ale nie gwarantuje dokładności nanosekundowej z powodu ograniczeń sprzętowych iOS/macOS. Do precyzyjnych pomiarów używaj mach_absolute_time lub ContinuousClock z Swift 5.7+, które działają na sprzętowych licznikach cykli procesora.

Podsumowanie

  • Date — typ wartościowy Foundation do przechowywania absolutnego momentu czasu jako TimeInterval od reference date 1 stycznia 2001 roku.
  • TimeInterval (Double) — liczba sekund między dwiema datami, zapewniająca porównanie i arytmetykę z Date.
  • Calendar i DateComponents — jedyny sposób na wydobycie z Date roku, miesiąca, dnia i innych komponentów kalendarzowych.
  • DateFormatter i ISO8601DateFormatter — niezbędne narzędzia do wyświetlania i serializacji dat w formacie tekstowym.
  • Date.distantPast i Date.distantFuture — wartości graniczne do filtrowania i sortowania w algorytmach.
  • Date nie zawiera timezone — strefa czasowa jest dodawana na poziomie Calendar przy wydobywaniu komponentów do wyświetlania.
  • Core Data i Codable obsługują Date natywnie, co upraszcza przechowywanie i przesyłanie dat bez dodatkowych przekształceń.

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również