在C#中处理时区:如何不错过与服务器的约会

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

时间——是相对的。尤其在代码中



想象一下:您正在编写一个机票预订应用程序。来自纽约的用户选择当地时间14:00的航班,而伦敦的服务器将其保存为DateTime.Now。会出什么问题?一切都会出问题。最好的情况——机票早了三个小时,最坏的情况——用户错过航班并留下愤怒的评论。



在C#中处理时区是许多开发人员“以后再说”的话题。但正是这一点将业余代码与专业代码区分开来。今天我们将弄清楚如何让您的应用程序与时区友好相处,不被夏令时逼疯,并且不丢失任何一个用户。



DateTime vs DateTimeOffset:与现实的第一次交锋



许多C#新手对所有事情都使用DateTime。这没问题,直到您遇到全球用户。问题在于DateTime本身不知道它处于哪个时区。它只是一个没有上下文的“时间点”。



// 不好:没有上下文的时间DateTime localTime = DateTime.Now; // 14:00 — 但在哪里?DateTime utcTime = DateTime.UtcNow; // 好一些,但仍然不理想

// 好:带偏移量的时间DateTimeOffset withOffset = DateTimeOffset.Now; // 14:00 +03:00Console.WriteLine(withOffset); // 06.04.2025 14:00:00 +03:00


DateTimeOffset——是您迈向有意识时间管理的第一步。它不仅存储日期和时间,还存储相对于UTC的偏移量。当需要在系统之间传输数据或只是向用户显示正确的本地时间时,这非常有用。



什么时候DateTime仍然需要?



说实话?几乎从不用于存储时间点。如果您为本地桌面应用程序编写代码——可以。但一旦出现数据库、API或多个用户——请切换到DateTimeOffset或显式指定DateTimeKind.Utc的DateTime。



TimeZoneInfo:您个人的时区地图集



.NET中有一个强大的类TimeZoneInfo。它允许您使用操作系统已知的任何时区。有数百个——从标准的UTC+0到像“豪勋爵岛”这样偏移30分钟的异域时区。



// 获取所有可用时区的列表ReadOnlyCollection<TimeZoneInfo> allZones = TimeZoneInfo.GetSystemTimeZones();foreach (var zone in allZones.Take(5)){    Console.WriteLine($"{zone.Id}: {zone.DisplayName}");}// 输出(示例):// UTC: (UTC) 协调世界时// Russian Standard Time: (UTC+03:00) 莫斯科,圣彼得堡// Eastern Standard Time: (UTC-05:00) 东部时间(美国和加拿大)


时区之间的时间转换



假设来自莫斯科的用户想知道伦敦的网络研讨会何时开始。以下是正确做法:



// 原始时间——莫斯科时间DateTime moscowTime = new DateTime(2025, 6, 15, 18, 0, 0);TimeZoneInfo moscowZone = TimeZoneInfo.FindSystemTimeZoneById("Russian Standard Time");TimeZoneInfo londonZone = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");

// 转换DateTime londonTime = TimeZoneInfo.ConvertTime(moscowTime, moscowZone, londonZone);Console.WriteLine($"在莫斯科: {moscowTime}, 在伦敦: {londonTime}");// 在莫斯科: 15.06.2025 18:00:00, 在伦敦: 15.06.2025 16:00:00


请注意:我们明确指定了源时区和目标时区。这消除了歧义。TimeZoneInfo.ConvertTime会自动考虑时差,包括夏令时/冬令时。



夏令时(DST):开发人员的主要敌人



每年两次,世界陷入混乱。三月时钟拨快,十月拨回。如果您的应用程序没有准备好应对夏令时,用户将看到“多余”的一小时或错过的一小时。C#会自动处理这个问题

博客

书籍推荐