La date et l'heure dans le développement mobile — l'un des sujets clés de l'ingénierie mobile. iOS utilise DateFormatter et ISO8601DateFormatter, Android utilise DateTimeFormatter et LocalDate de java.time. Selon Android Developer Docs, le choix de la bonne API mobile pour le formatage de la date et de l'heure affecte directement les performances et la précision d'affichage dans différents fuseaux horaires.
Points clés
Sur iOS, la date et l'heure sont traditionnellement formatées via DateFormatter de Foundation. Cette classe convertit Date en chaîne et vice-versa en utilisant un motif, une locale et un fuseau horaire spécifiés. Le principal problème de DateFormatter — il n'est pas thread-safe et sa création est lente, donc dans le code mobile, les instances doivent être mises en cache. La date dans le développement mobile sur iOS nécessite le bon formateur.
La création d'un DateFormatter prend environ 1 milliseconde en raison de l'analyse du motif dateFormat, du chargement de la locale et de la détermination du fuseau horaire. Lors du formatage d'une liste de centaines de dates, la création répétée entraîne des ralentissements notables dans l'interface utilisateur. La solution — créez le formateur une fois pour tout l'écran et réutilisez-le. Pour l'accès multithread, utilisez la synchronisation via DispatchQueue.
import Foundation
// DateFormatter mis en cache — créé une fois
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 — alternative légère
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"
Pour le format ISO 8601, utilisez ISO8601DateFormatter — il ne nécessite pas de spécifier de motif et fonctionne plus rapidement que DateFormatter. Sur iOS 10+, cette classe est préférable pour travailler avec les dates serveur. Pour les anciens formats, gardez DateFormatter mais mettez impérativement en cache l'instance comme propriété statique ou singleton.
Sur Android, la date et l'heure sont traitées via le package java.time, disponible depuis l'API 26. Classes principales : LocalDate (date uniquement), LocalTime (heure uniquement), LocalDateTime (date et heure sans fuseau horaire) et ZonedDateTime (avec fuseau horaire). DateTimeFormatter — un formateur thread-safe pour la plateforme mobile Android. La date dans les applications mobiles est formatée via DateTimeFormatter et LocalDate sans perte de performances.
LocalDate stocke la date sans heure — idéal pour les anniversaires. ZonedDateTime stocke les informations complètes avec le fuseau horaire. DateTimeFormatter prend en charge les motifs prédéfinis (ISO_LOCAL_DATE, ISO_DATE_TIME) et personnalisés via ofPattern. Toutes les classes java.time sont immuables et thread-safe, ce qui élimine les conditions de concurrence lors du travail dans plusieurs threads.
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.time.ZoneId
// Créer et formater la date actuelle
val today = LocalDate.now()
val formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy")
val formatted = today.format(formatter)
// Travailler avec les fuseaux horaires
val utcTime = ZonedDateTime.now(ZoneId.of("UTC"))
val moscowTime = utcTime.withZoneSameInstant(ZoneId.of("Europe/Moscow"))
DateTimeFormatter est nettement plus performant que SimpleDateFormat car il n'analyse pas le motif à chaque appel. Il est recommandé de créer des constantes de formateur au niveau de la classe ou de l'objet compagnon. Pour convertir un Unix Timestamp, utilisez Instant.ofEpochSecond, puis convertissez en LocalDateTime ou ZonedDateTime via le fuseau horaire.
La date et l'heure correctes sur l'écran de l'utilisateur dépendent d'un traitement approprié des fuseaux horaires. La date et l'heure dans le développement mobile pour Android nécessite la prise en compte du fuseau horaire de l'appareil. La règle d'or : stockez l'heure en UTC, convertissez dans le fuseau horaire local uniquement pour l'affichage. iOS fournit TimeZone de Foundation, Android fournit ZoneId de java.time. Les deux API pour plateformes mobiles prennent en charge la détection automatique du fuseau horaire actuel de l'appareil. La date dans une application mobile dépend de ZoneId et de TimeZone.
L'heure d'été crée une ambiguïté : un moment dans le temps peut être représenté par deux heures locales différentes. java.time et Foundation gèrent le DST automatiquement. Utilisez les identifiants IANA (Europe/Moscow, America/New_York), pas les abréviations (MSK, EST) — les abréviations sont ambiguës et ignorent le passage à l'heure d'été.
import Foundation
// Convertir UTC en heure locale sur 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)
}
// Déterminer le fuseau horaire de l'appareil
let localTimeZone = TimeZone.current
let isDST = localTimeZone.isDaylightSavingTime()
let secondsFromGMT = localTimeZone.secondsFromGMT()
Sur Android, utilisez ZoneId.systemDefault() pour obtenir le fuseau horaire de l'appareil. Lors de la conversion d'UTC en heure locale, créez un ZonedDateTime avec ZoneOffset.UTC et appliquez withZoneSameInstant. Pour les anciennes API sans java.time, utilisez TimeZone.getDefault() et Calendar — mais il est préférable d'ajouter directement ThreeTenABP.
import java.time.Instant
import java.time.ZonedDateTime
import java.time.ZoneId
// Convertir Unix Timestamp en heure 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 — une bibliothèque adaptatrice qui porte java.time sur Android API inférieure à 26. Elle fournit les mêmes classes : LocalDate, LocalTime, ZonedDateTime, DateTimeFormatter, Instant. Si l'application prend en charge Android 5 ou 6 (API 21-25), ThreeTenABP est le seul moyen d'utiliser une API mobile moderne sans migrer vers l'obsolète Calendar. La date et l'heure dans le développement mobile pour les anciens appareils sont implémentées via cette bibliothèque. Pour les anciens appareils, la date et l'heure sont implémentées via ThreeTenABP.
La bibliothèque nécessite une initialisation dans la méthode Application.onCreate() en appelant AndroidThreeTen.init(). Cela charge les données de fuseaux horaires depuis assets. Après initialisation, l'API est totalement identique à java.time — le code pour API 26+ et pour API 21+ sera le même. La taille de la bibliothèque est d'environ 400 Ko, ce qui est acceptable pour la plupart des applications mobiles.
import org.threeten.bp.LocalDate
import org.threeten.bp.format.DateTimeFormatter
// Initialisation dans Application
class App : Application() {
override fun onCreate() {
super.onCreate()
AndroidThreeTen.init(this)
}
}
// API est identique à java.time
val today = LocalDate.now()
val formatted = today.format(DateTimeFormatter.ISO_LOCAL_DATE)
Les performances de ThreeTenABP sont comparables à java.time original sur les appareils modernes. Sur les anciens appareils, un délai peut survenir au premier appel en raison du chargement des données de fuseaux horaires. Migrez le code existant de Calendar vers ThreeTenABP progressivement : remplacez Date et Calendar par Instant et LocalDate dans les nouveaux modules, en laissant l'ancien code inchangé.
Unix Timestamp — le nombre de secondes écoulées depuis le 1er janvier 1970 00:00 UTC. C'est un format universel pour stocker et échanger le temps entre le serveur et le client. Cependant, l'heure sur l'appareil peut différer de l'heure réelle en raison des paramètres de l'utilisateur. Pour la synchronisation, on utilise NTP — un protocole de temps précis via UDP. Unix Timestamp est le format dans lequel la date et l'heure sont stockées sur le serveur.
Date().timeIntervalSince1970 sur iOS retourne les secondes depuis 1970. Sur Android, System.currentTimeMillis() retourne les millisecondes. Pour la précision, utilisez NTP : la bibliothèque TrueTime pour iOS et AndroidNtp pour Android envoient une requête à un serveur NTP et calculent le décalage horaire. La précision du NTP est de 1 à 10 ms sur un réseau local et de 10 à 100 ms via Internet.
import Foundation
// Obtenir Unix Timestamp sur iOS
let seconds = Date().timeIntervalSince1970
let milliseconds = Int64(seconds * 1000)
// Synchronisation NTP avec TrueTime
TrueTime.shared.start { result in
switch result {
case .success:
let ntpTime = TrueTime.shared.now()
print("Heure exacte : \(ntpTime)")
case .failure(let error):
print("Erreur NTP : \(error)")
}
}
Sans synchronisation dans une application mobile, des erreurs sont possibles : horodatages incorrects d'événements, désynchronisation avec le serveur. Le temps dans le développement mobile est synchronisé via NTP une fois au démarrage de l'application, après quoi le décalage calculé est utilisé. Pour les applications mobiles critiques en termes de précision (finance, logistique), le protocole NTP est obligatoire avant d'envoyer des données au serveur.
Questions fréquentes
DateFormatter analyse le motif de formatage, charge la locale et détermine le fuseau horaire à chaque création d'instance. Mettez en cache le formateur comme constante statique ou utilisez ISO8601DateFormatter pour ISO 8601 — il est plus léger et plus rapide.
DateTimeFormatter du package java.time — thread-safe et performant. Disponible depuis l'API 26. Pour les anciennes versions, utilisez ThreeTenABP qui fournit une API identique.
Ajoutez ThreeTenABP — un backport de java.time pour Android API 21+. Initialisez via AndroidThreeTen.init() dans Application.onCreate(). L'API est totalement identique à java.time original.
Oui, stockez l'heure en UTC sur le serveur et dans la base de données locale. Convertissez dans le fuseau horaire local de l'utilisateur uniquement lors de l'affichage. Cela élimine les erreurs lors des changements de fuseau horaire ou des voyages.
Date().timeIntervalSince1970 retourne le nombre de secondes depuis le 1er janvier 1970. Pour les millisecondes, multipliez par 1000 et convertissez en Int64. Pour une synchronisation précise, utilisez la bibliothèque TrueTime avec un serveur NTP.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.