Date è una struttura di Foundation che rappresenta un momento specifico nel tempo, indipendentemente dal calendario e dal fuso orario. Il tipo memorizza il numero di secondi trascorsi dalla data di riferimento del 1° gennaio 2001 e fornisce operazioni di base per il confronto e il calcolo degli intervalli di tempo. Secondo la documentazione Apple Developer (2025), Date viene utilizzato in tutti i framework Apple: da UIKit e SwiftUI a CloudKit e Core Data. Comprendere il funzionamento di Date è essenziale per qualsiasi sviluppatore iOS, poiché senza di esso è impossibile gestire il tempo in un'applicazione.
Punti chiave
Date è un tipo valore del framework Foundation che cattura un singolo momento assoluto nel tempo. A differenza delle rappresentazioni di calendario (anno, mese, giorno), Date non dipende dal fuso orario o dal sistema di calendario — è un valore di timestamp puramente numerico.
La rappresentazione interna di Date è TimeInterval (un alias di tipo per Double), che memorizza il numero di secondi relativi alla data di riferimento — 1° gennaio 2001, 00:00:00 UTC. Apple ha scelto questa data invece dell'epoca Unix (1970) per compatibilità con i sistemi legacy NeXTSTEP, su cui iOS e macOS sono costruiti.
Date viene utilizzato come tipo di tempo standard in tutte le API Apple: UIDatePicker, DatePicker, UserDefaults, Codable, Core Data, CloudKit. Senza Date, è impossibile lavorare con programmi, timer, eventi del calendario, serializzazione dei dati e qualsiasi operazione relativa al tempo.
Date si differenzia dai tipi di calendario in quanto rappresenta un timestamp fisico piuttosto che un valore leggibile dall'uomo. La stessa Date può corrispondere a diverse date di calendario in diversi fusi orari. Per estrarre componenti (anno, mese, giorno), Date viene convertito tramite Calendar e DateComponents.
Date si differenzia anche da DispatchTime, che viene utilizzato per l'invio di attività in Grand Central Dispatch. DispatchTime è relativo al momento di avvio del sistema, mentre Date è un timestamp assoluto che può essere salvato, trasmesso e ripristinato.
Date() è il modo più semplice per creare un oggetto con il momento corrente. L'inizializzatore senza parametri restituisce l'ora esatta della chiamata. Per creare una data nel passato o nel futuro, utilizzare TimeInterval e il metodo addingTimeInterval, o l'inizializzazione da una Date esistente.
Per creare una data arbitraria da componenti, utilizzare la coppia Calendar e DateComponents. Calendar converte i componenti leggibili dall'uomo (anno, mese, giorno, ora, minuto) in Date. È possibile anche inizializzare Date tramite ISO8601DateFormatter da una stringa ISO 8601, o tramite DateFormatter da una rappresentazione di stringa arbitraria.
Date.distantPast e Date.distantFuture sono due proprietà statiche che rappresentano momenti infinitamente distanti nel passato e nel futuro. Vengono utilizzati come valori limite per filtrare e ordinare le date negli algoritmi.
import Foundation
// Creare Date con l'ora corrente
let now = Date()
print("Current time: \(now)")
// Data in 1 ora (3600 secondi)
let inOneHour = now.addingTimeInterval(3600)
// Data da componenti
var components = DateComponents()
components.year = 2025
components.month = 12
components.day = 25
let christmas = Calendar.current.date(from: components)!
L'esempio mostra tre modi per creare una Date: ora corrente, aggiunta di un intervallo e creazione tramite DateComponents. Tutti e tre gli approcci restituiscono un valore di tipo Date con precisione al millisecondo. Calendar.current utilizza il calendario di sistema dell'utente — sui dispositivi Apple, questo è tipicamente il calendario gregoriano.
TimeInterval è un alias di tipo per Double che rappresenta il numero di secondi tra due momenti nel tempo. La precisione di TimeInterval raggiunge frazioni di millisecondo, sufficiente per la maggior parte delle attività pratiche. Un TimeInterval negativo indica il passato rispetto al punto di riferimento.
Date supporta tutti gli operatori di confronto standard: ==, <, >, <=, >=. Swift confronta automaticamente i valori TimeInterval interni. Il metodo compare restituisce ComparisonResult con le opzioni .orderedSame, .orderedAscending, .orderedDescending per un confronto più esplicito.
Date.distance(to:) è un metodo che restituisce il TimeInterval fino alla data specificata. Se la data di destinazione è nel passato, il risultato è negativo. advanced(by:) crea una nuova data aggiungendo il TimeInterval specificato a quella corrente. Questi metodi implementano il protocollo Strideable, consentendo di utilizzare Date in Range e ClosedRange.
let start = Date()
let end = start.addingTimeInterval(86400)
// Confronto tramite operatori
if start < end {
print("start is earlier")
}
// TimeInterval tra due date
let interval: TimeInterval = end.timeIntervalSince(start)
print("Seconds: \(Int(interval / 60)) minutes")
// Usare Date in un intervallo
let range = start...end
let mid = start.addingTimeInterval(43200)
if range.contains(mid) {
print("mid is between start and end")
}
TimeInterval di 86400 corrisponde a un giorno. Per intervalli più complessi — settimane, mesi, anni — utilizzare Calendar e DateComponents, poiché queste unità hanno lunghezza variabile (anni bisestili, ora legale). TimeInterval è applicabile solo per intervalli fissi in secondi.
Calendar è il ponte tra Date e i componenti leggibili dall'uomo. Calendar converte Date in DateComponents (anno, mese, giorno, ora, minuto, secondo) tenendo conto del fuso orario e delle impostazioni locali. Senza Calendar, è impossibile estrarre l'anno o il mese da Date — Date non contiene queste informazioni a causa della sua natura assoluta.
Il metodo Calendar.component estrae un singolo componente da Date: anno, mese, giorno, ora, minuto, secondo, giorno della settimana, trimestre. Il metodo Calendar.dateComponents estrae un insieme di componenti in una singola chiamata — questo è più efficiente che chiamare component per ogni campo separatamente.
Calendar.isDateInToday, isDateInTomorrow, isDateInYesterday sono metodi convenienti per verificare le date relative. Calendar.dateInterval restituisce l'inizio e la fine del periodo specificato (giorno, settimana, mese, anno). Calendar.compare confronta le date con precisione fino al componente specificato — ad esempio, anno senza considerare mese e giorno.
let calendar = Calendar.current
// Estrarre componenti
let year = calendar.component(.year, from: Date())
let month = calendar.component(.month, from: Date())
// Verificare data relativa
if calendar.isDateInToday(someDate) {
print("Today!")
}
// Inizio e fine del giorno
let dayInterval = calendar.dateInterval(of: .day, for: Date())!
print("Day start: \(dayInterval.start)")
print("Day end: \(dayInterval.end)")
Calendar.current utilizza le impostazioni di sistema dell'utente — calendario, fuso orario e impostazioni locali. Per test o calcoli specifici, è possibile creare un Calendar con parametri specifici tramite Calendar(identifier: .gregorian) e impostare il fuso orario desiderato tramite la proprietà timeZone.
DateFormatter è un componente obbligatorio se Date deve essere visualizzato all'utente. DateFormatter converte Date in una stringa secondo il formato e le impostazioni locali specificate. Convertire Date direttamente in stringa tramite String(describing:) restituisce una rappresentazione tecnica con la data di riferimento e TimeInterval — non è destinata agli utenti.
L'approccio di base è utilizzare gli stili predefiniti dateStyle e timeStyle. iOS supporta quattro stili: .short, .medium, .long, .full. La combinazione di stili di data e ora consente una configurazione flessibile della visualizzazione. DateFormatter applica automaticamente la localizzazione: per le impostazioni locali russe, la data verrà visualizzata nel formato “21 luglio 2026”.
ISO8601DateFormatter è un formattatore specializzato per ISO 8601, il formato più comune per API e scambio di dati. Questo formattatore funziona più velocemente di DateFormatter e non dipende dalle impostazioni locali, rendendolo preferibile per la serializzazione delle date in JSON.
// Stili predefiniti
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .short
let userString = formatter.string(from: Date())
// ISO 8601 per API
let isoFormatter = ISO8601DateFormatter()
let apiString = isoFormatter.string(from: Date())
// Parsing da stringa
let parsed = isoFormatter.date(from: "2026-07-21T10:30:00Z")!
Quando si lavora con DateFormatter, è importante ricordare le prestazioni: creare un nuovo formattatore è un'operazione costosa. Si consiglia di memorizzare nella cache il formattatore o crearlo una volta e riutilizzarlo. Le proprietà del formattatore consentono di impostare timeZone — per impostazione predefinita viene utilizzato il fuso orario di sistema, ma per le date del server è spesso richiesto TimeZone(identifier: “UTC”).
Consideriamo scenari tipici per lavorare con Date in un'applicazione iOS. Il primo scenario è il calcolo dell'età dalla data di nascita dell'utente. Il secondo è un timer di conto alla rovescia per un evento. Il terzo è il raggruppamento dei record per data per la visualizzazione come sezioni di tabella.
Calendar.dateComponents con il flag [.year] calcola la differenza tra due date. Impostare il fuso orario corretto è critico — se non si specifica timeZone in Calendar, il risultato potrebbe differire di un giorno a causa del passaggio della mezzanotte in un altro fuso orario.
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
}
Timer di conto alla rovescia viene implementato utilizzando TimeInterval. Calcolare la differenza tra la data di destinazione e la data corrente, ottenere il resto in secondi e convertire in giorni, ore, minuti. Per aggiornamenti regolari, utilizzare Timer con un intervallo di 1 secondo. Un ObservableObject con una proprietà @Published consente a SwiftUI di aggiornare automaticamente l'interfaccia.
Raggruppamento per data viene implementato utilizzando un dizionario con Date come chiave. Calendar.dateInterval(of: .day, for:) normalizza la data all'inizio del giorno, consentendo di raggruppare i record appartenenti allo stesso giorno. Lo stesso approccio funziona per settimane, mesi e anni — basta cambiare il componente in dateInterval in .weekOfYear o .month.
| Scenario | API chiave | Note |
|---|---|---|
| Calcolo età | Calendar.dateComponents | Considerare timeZone |
| Conto alla rovescia | Date.timeIntervalSince | Timer+Combine |
| Raggruppamento date | Calendar.dateInterval | Normalizzare al giorno |
| Serializzazione JSON | ISO8601DateFormatter | Locale non influisce |
Domande frequenti
Date è una rappresentazione interna del tempo senza legame con calendario e impostazioni locali. Una stringa è una visualizzazione formattata dipendente dalle impostazioni dell'utente. Date può essere confrontato, serializzato ed elaborato matematicamente con precisione al 100%, mentre la rappresentazione in stringa richiede sempre l'analisi tramite un formattatore.
Date è un timestamp assoluto (numero di secondi dalla data di riferimento) che non dipende dal fuso orario. Il fuso orario è un contesto di visualizzazione. La stessa Date in UTC e a Mosca rappresenta lo stesso momento fisico ma viene visualizzata come un'ora di calendario diversa.
Date è supportato nativamente da Core Data come tipo di attributo. Core Data serializza automaticamente Date nell'archivio. Per le query con filtro per data, utilizzare NSPredicate con operatori di confronto — Core Data gestisce correttamente il fuso orario a livello SQLite.
CFAbsoluteTime è un tipo Core Foundation che utilizza la stessa data di riferimento (1° gennaio 2001). Date e CFAbsoluteTime sono intercambiabili tramite conversione diretta. Date(timeIntervalSinceReferenceDate:) accetta CFAbsoluteTime e Date.timeIntervalSinceReferenceDate restituisce CFAbsoluteTime.
Date ha una precisione al millisecondo ma non garantisce precisione al nanosecondo a causa delle limitazioni hardware di iOS/macOS. Per misurazioni di alta precisione, utilizzare mach_absolute_time o ContinuousClock da Swift 5.7+, che funzionano su contatori di cicli del processore.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche