Data e ora nello sviluppo mobile — uno dei temi chiave dell'ingegneria mobile. iOS utilizza DateFormatter e ISO8601DateFormatter, Android utilizza DateTimeFormatter e LocalDate da java.time. Secondo Android Developer Docs, la scelta corretta dell'API mobile per la formattazione di data e ora influisce direttamente sulle prestazioni e sulla corretta visualizzazione in diversi fusi orari.
Punti chiave
Su iOS, data e ora vengono tradizionalmente formattate tramite DateFormatter di Foundation. Questa classe converte Date in stringa e viceversa utilizzando un pattern, una locale e un fuso orario specificati. Il problema principale di DateFormatter — non è thread-safe e viene creato lentamente, quindi nel codice mobile le istanze devono essere messe in cache. La data nello sviluppo mobile su iOS richiede il formattatore corretto.
La creazione di un DateFormatter richiede circa 1 millisecondo a causa dell'analisi del pattern dateFormat, del caricamento della locale e della determinazione del fuso orario. Quando si formatta un elenco di centinaia di date, la creazione ripetuta porta a ritardi evidenti nell'interfaccia utente. La soluzione — crea il formattatore una volta per l'intero schermo e riutilizzalo. Per l'accesso multi-thread, utilizza la sincronizzazione tramite DispatchQueue.
import Foundation
// DateFormatter in cache — creato una volta
private let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "dd.MM.yyyy HH:mm"
formatter.locale = Locale(identifier: "ru_RU")
formatter.timeZone = TimeZone(identifier: "Europe/Moscow")
return formatter
}()
// ISO8601DateFormatter — alternativa leggera
private let isoFormatter: ISO8601DateFormatter = {
let formatter = ISO8601DateFormatter()
formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
return formatter
}()
let now = Date()
let formattedDate = dateFormatter.string(from: now)
// "01.07.2026 14:30"
let isoDate = isoFormatter.string(from: now)
// "2026-07-01T14:30:00.000Z"
Per il formato ISO 8601, utilizza ISO8601DateFormatter — non richiede la specifica di un pattern e funziona più velocemente di DateFormatter. Su iOS 10+, questa classe è preferibile per lavorare con le date del server. Per i vecchi formati, mantieni DateFormatter ma assicurati di mantenere in cache l'istanza come proprietà statica o singleton.
Su Android, data e ora vengono gestite tramite il pacchetto java.time, disponibile dall'API 26. Classi principali: LocalDate (solo data), LocalTime (solo ora), LocalDateTime (data e ora senza fuso orario) e ZonedDateTime (con fuso orario). DateTimeFormatter — un formattatore thread-safe per la piattaforma mobile Android. La data nelle applicazioni mobili viene formattata tramite DateTimeFormatter e LocalDate senza perdita di prestazioni.
LocalDate archivia la data senza ora — ideale per i compleanni. ZonedDateTime archivia le informazioni complete con fuso orario. DateTimeFormatter supporta pattern predefiniti (ISO_LOCAL_DATE, ISO_DATE_TIME) e personalizzati tramite ofPattern. Tutte le classi java.time sono immutabili e thread-safe, eliminando le race condition quando si lavora in più thread.
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.time.ZoneId
// Creare e formattare la data corrente
val today = LocalDate.now()
val formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy")
val formatted = today.format(formatter)
// Lavorare con i fusi orari
val utcTime = ZonedDateTime.now(ZoneId.of("UTC"))
val moscowTime = utcTime.withZoneSameInstant(ZoneId.of("Europe/Moscow"))
DateTimeFormatter è significativamente più performante di SimpleDateFormat perché non analizza il pattern a ogni chiamata. Si consiglia di creare costanti di formattatore a livello di classe o oggetto companion. Per convertire un Unix Timestamp, utilizza Instant.ofEpochSecond, poi converti in LocalDateTime o ZonedDateTime tramite il fuso orario.
La data e ora corretta sullo schermo dell'utente dipende dalla corretta gestione dei fusi orari. Data e ora nello sviluppo mobile per Android richiede la considerazione del fuso orario del dispositivo. La regola d'oro: archivia l'ora in UTC, converti nel fuso orario locale solo per la visualizzazione. iOS fornisce TimeZone da Foundation, Android fornisce ZoneId da java.time. Entrambe le API per piattaforme mobili supportano il rilevamento automatico del fuso orario corrente del dispositivo. La data in un'applicazione mobile dipende da ZoneId e TimeZone.
L'ora legale crea ambiguità: un momento nel tempo può essere rappresentato da due ore locali diverse. java.time e Foundation gestiscono automaticamente l'ora legale. Utilizza identificatori IANA (Europe/Moscow, America/New_York), non abbreviazioni (MSK, EST) — le abbreviazioni sono ambigue e ignorano il passaggio all'ora legale.
import Foundation
// Convertire UTC in ora locale su iOS
func formatToLocalTime(utcDate: Date, timeZoneId: String) -> String {
let formatter = DateFormatter()
formatter.dateFormat = "dd.MM.yyyy HH:mm"
formatter.timeZone = TimeZone(identifier: timeZoneId)
return formatter.string(from: utcDate)
}
// Determinare il fuso orario del dispositivo
let localTimeZone = TimeZone.current
let isDST = localTimeZone.isDaylightSavingTime()
let secondsFromGMT = localTimeZone.secondsFromGMT()
Su Android, utilizza ZoneId.systemDefault() per ottenere il fuso orario del dispositivo. Quando converti UTC in ora locale, crea un ZonedDateTime con ZoneOffset.UTC e applica withZoneSameInstant. Per le vecchie API senza java.time, utilizza TimeZone.getDefault() e Calendar — ma è meglio aggiungere direttamente ThreeTenABP.
import java.time.Instant
import java.time.ZonedDateTime
import java.time.ZoneId
// Convertire Unix Timestamp in ora locale
fun toLocalDisplay(unixSeconds: Long): String {
val instant = Instant.ofEpochSecond(unixSeconds)
val local = instant.atZone(ZoneId.systemDefault())
return local.format(DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm"))
}
ThreeTenABP — una libreria adattatrice che porta java.time su Android API inferiore a 26. Fornisce le stesse classi: LocalDate, LocalTime, ZonedDateTime, DateTimeFormatter, Instant. Se l'applicazione supporta Android 5 o 6 (API 21-25), ThreeTenABP è l'unico modo per utilizzare un'API mobile moderna senza migrare al deprecato Calendar. Data e ora nello sviluppo mobile per dispositivi vecchi è implementata tramite questa libreria. Per i dispositivi vecchi, data e ora sono implementate tramite ThreeTenABP.
La libreria richiede l'inizializzazione nel metodo Application.onCreate() chiamando AndroidThreeTen.init(). Questo carica i dati dei fusi orari dagli assets. Dopo l'inizializzazione, l'API è totalmente identica a java.time — il codice per API 26+ e per API 21+ sarà lo stesso. La dimensione della libreria è di circa 400 KB, accettabile per la maggior parte delle applicazioni mobili.
import org.threeten.bp.LocalDate
import org.threeten.bp.format.DateTimeFormatter
// Inizializzazione in Application
class App : Application() {
override fun onCreate() {
super.onCreate()
AndroidThreeTen.init(this)
}
}
// API è identica a java.time
val today = LocalDate.now()
val formatted = today.format(DateTimeFormatter.ISO_LOCAL_DATE)
Le prestazioni di ThreeTenABP sono paragonabili a java.time originale sui dispositivi moderni. Sui dispositivi vecchi, potrebbe esserci un ritardo alla prima chiamata a causa del caricamento dei dati dei fusi orari. Migra il codice esistente da Calendar a ThreeTenABP gradualmente: sostituisci Date e Calendar con Instant e LocalDate nei nuovi moduli, lasciando il vecchio codice invariato.
Unix Timestamp — il numero di secondi trascorsi dal 1° gennaio 1970 00:00 UTC. Questo è un formato universale per archiviare e scambiare il tempo tra server e client. Tuttavia, l'ora sul dispositivo può differire dall'ora reale a causa delle impostazioni dell'utente. Per la sincronizzazione viene utilizzato NTP — un protocollo di tempo preciso via UDP. Unix Timestamp è il formato in cui data e ora vengono archiviate sul server.
Date().timeIntervalSince1970 su iOS restituisce secondi dal 1970. Su Android, System.currentTimeMillis() restituisce millisecondi. Per la precisione, utilizza NTP: la libreria TrueTime per iOS e AndroidNtp per Android inviano una richiesta a un server NTP e calcolano lo scostamento orario. La precisione di NTP è di 1-10 ms su rete locale e 10-100 ms via internet.
import Foundation
// Ottenere Unix Timestamp su iOS
let seconds = Date().timeIntervalSince1970
let milliseconds = Int64(seconds * 1000)
// Sincronizzazione NTP con TrueTime
TrueTime.shared.start { result in
switch result {
case .success:
let ntpTime = TrueTime.shared.now()
print("Ora esatta: \(ntpTime)")
case .failure(let error):
print("Errore NTP: \(error)")
}
}
Senza sincronizzazione in un'applicazione mobile, sono possibili errori: timestamp di eventi errati, desincronizzazione con il server. Il tempo nello sviluppo mobile viene sincronizzato via NTP una volta all'avvio dell'applicazione, dopo di che viene utilizzato lo scostamento calcolato. Per le applicazioni mobili critiche in termini di precisione (finanza, logistica), il protocollo NTP è obbligatorio prima di inviare i dati al server.
Domande frequenti
DateFormatter analizza il pattern di formattazione, carica la locale e determina il fuso orario ogni volta che viene creata un'istanza. Mantieni in cache il formattatore come costante statica o utilizza ISO8601DateFormatter per ISO 8601 — è più leggero e veloce.
DateTimeFormatter dal pacchetto java.time — thread-safe e performante. Disponibile dall'API 26. Per le vecchie versioni, utilizza ThreeTenABP che fornisce un'API identica.
Aggiungi ThreeTenABP — un backport di java.time per Android API 21+. Inizializza tramite AndroidThreeTen.init() in Application.onCreate(). L'API è totalmente identica a java.time originale.
Sì, archivia l'ora in UTC sul server e nel database locale. Converti nel fuso orario locale dell'utente solo nella fase di visualizzazione. Questo elimina gli errori al cambio di fuso orario o durante i viaggi.
Date().timeIntervalSince1970 restituisce il numero di secondi dal 1° gennaio 1970. Per i millisecondi, moltiplica per 1000 e converti in Int64. Per una sincronizzazione precisa, utilizza la libreria TrueTime con un server NTP.
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.