Le temps est une chose relative. Surtout dans le code
Imaginez : vous développez une application de réservation de billets d'avion. Un utilisateur de New York choisit un vol à 14h00 heure locale, et le serveur à Londres enregistre cela comme DateTime.Now. Qu'est-ce qui pourrait mal tourner ? Absolument tout. Dans le meilleur des cas, le billet est pour trois heures plus tôt, dans le pire, l'utilisateur rate son vol et laisse un avis cinglant.
Travailler avec les fuseaux horaires en C# est un sujet que de nombreux développeurs remettent « à plus tard ». Mais c'est précisément ce qui sépare le code amateur du code professionnel. Aujourd'hui, nous allons voir comment faire cohabiter votre application avec les fuseaux horaires, sans perdre la tête avec l'heure d'été et sans perdre un seul utilisateur.
DateTime vs DateTimeOffset : premier combat avec la réalité
De nombreux débutants en C# utilisent DateTime pour tout. Et c'est normal, jusqu'à ce que vous soyez confronté à des utilisateurs globaux. Le problème est que DateTime en lui-même ne connaît pas son fuseau horaire. C'est juste un « instant dans le temps » sans contexte.
// Mauvais : heure sans contexteDateTime localTime = DateTime.Now; // 14:00 — mais où ?DateTime utcTime = DateTime.UtcNow; // mieux, mais pas encore idéal
// Bon : heure avec décalageDateTimeOffset withOffset = DateTimeOffset.Now; // 14:00 +03:00Console.WriteLine(withOffset); // 06.04.2025 14:00:00 +03:00DateTimeOffset est votre premier pas vers une gestion consciente du temps. Il stocke non seulement la date et l'heure, mais aussi le décalage par rapport à UTC. Cela vous sauve lorsque vous devez transférer des données entre systèmes ou simplement afficher l'heure locale correcte à l'utilisateur.
Quand DateTime est-il quand même nécessaire ?
Honnêtement ? Presque jamais pour stocker des instants dans le temps. Si vous écrivez du code pour une application de bureau locale, c'est possible. Mais dès qu'une base de données, une API ou plusieurs utilisateurs apparaissent, passez à DateTimeOffset ou à DateTime avec indication explicite de DateTimeKind.Utc.
TimeZoneInfo : votre atlas personnel des fuseaux horaires
Dans .NET, il existe une classe puissante TimeZoneInfo. Elle permet de travailler avec tous les fuseaux horaires connus du système d'exploitation. Et il y en a des centaines — des standards UTC+0 aux zones exotiques comme « Lord Howe Island » avec un décalage de 30 minutes.
// Obtenir la liste de toutes les zones disponiblesReadOnlyCollection<TimeZoneInfo> allZones = TimeZoneInfo.GetSystemTimeZones();foreach (var zone in allZones.Take(5)){ Console.WriteLine($"{zone.Id}: {zone.DisplayName}");}// Sortie (exemple) :// UTC: (UTC) Coordinated Universal Time// Russian Standard Time: (UTC+03:00) Moscow, St. Petersburg// Eastern Standard Time: (UTC-05:00) Eastern Time (US & Canada)Conversion de l'heure entre les zones
Supposons qu'un utilisateur de Moscou veuille savoir à quelle heure commence un webinaire à Londres. Voici comment faire correctement :
// Heure d'origine — heure de MoscouDateTime moscowTime = new DateTime(2025, 6, 15, 18, 0, 0);TimeZoneInfo moscowZone = TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time");TimeZoneInfo londonZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
// ConversionDateTime londonTime = TimeZoneInfo.ConvertTime(moscowTime, moscowZone, londonZone);Console.WriteLine($"À Moscou : {moscowTime}, à Londres : {londonTime}");// À Moscou : 15.06.2025 18:00:00, à Londres : 15.06.2025 16:00:00Remarquez : nous indiquons explicitement les zones source et cible. Cela élimine toute ambiguïté. TimeZoneInfo.ConvertTime prendra lui-même en compte la différence horaire, y compris l'heure d'été/hiver.
Heure d'été (DST) : l'ennemi numéro un du développeur
Deux fois par an, le monde devient fou. En mars, on avance les horloges, en octobre, on les recule. Et si votre application n'est pas prête pour le DST, les utilisateurs verront soit une heure « en trop », soit une heure manquante. C# gère cela automat