在 C# (.NET) 中处理日期:内置工具与库的完整概览
日期和时间处理是开发中最常见的任务之一。在 C# (.NET) 生态系统中,既有强大的内置功能(System.DateTime),也有简化复杂场景(如时区处理、格式化、时间间隔和解析)的第三方库。在本文中,我们将分析主要工具,包括 .NET 6+ 的现代功能和流行的 NuGet 包。
1. 内置工具:DateTime、DateOnly、TimeOnly
基础类 System.DateTime 自 .NET 早期版本起就已可用。它支持:
- 创建日期:
new DateTime(2025, 3, 15) - 算术运算:
date.AddDays(10)、date.AddMonths(-1) - 比较:
date1 > date2 - 格式化:
date.ToString("yyyy-MM-dd")
从 .NET 6 开始,新增了 DateOnly 和 TimeOnly 类型——它们不绑定时区,仅存储日期或仅存储时间。这对于生日、工作时间和日程安排非常方便。
using System;
DateOnly birthday = new DateOnly(1990, 5, 20);TimeOnly alarm = new TimeOnly(7, 30);
Console.WriteLine($"日期: {birthday}, 时间: {alarm}");// 输出: 日期: 20.05.1990, 时间: 07:302. TimeSpan — 时间间隔
用于处理时间间隔的是 TimeSpan。它可以计算日期之间的差值、操作持续时间和超时时间。
DateTime start = DateTime.Now;// ... 执行代码 ...DateTime end = DateTime.Now;
TimeSpan elapsed = end - start;Console.WriteLine($"已过: {elapsed.TotalSeconds} 秒");3. Noda Time — 高级日期处理
Noda Time(NuGet: NodaTime)—— 这是 Jon Skeet(C# 畅销书作者)开发的库。它解决了 DateTime 的问题:
- 清晰区分“时间点”(
Instant)、“日历日期”(LocalDate)和“带时区的时间”(ZonedDateTime)。 - 支持多种日历(伊斯兰历、希伯来历、日本历)。
- 所有类型均为不可变。
- 通过 IANA 时区数据库(tzdata)正确进行时区处理。
using NodaTime;
Instant now = SystemClock.Instance.GetCurrentInstant();DateTimeZone zone = DateTimeZoneProviders.Tzdb["Europe/Moscow"];ZonedDateTime moscowTime = now.InZone(zone);
Console.WriteLine($"莫斯科当前时间: {moscowTime:yyyy-MM-dd HH:mm}");
// 使用 LocalDateLocalDate today = LocalDate.FromDateTime(DateTime.Today);LocalDate nextWeek = today.PlusDays(7);Noda Time 在时区精度至关重要的项目中特别有用(日志、预订、国际系统)。
4. Humanizer — 人性化日期显示
Humanizer(NuGet: Humanizer.Core)—— 用于将数字、日期和时间转换为自然语言的库。它可以:
- 显示相对时间:“3 分钟前”、“2 天后”。
- 变格月份和星期名称。
- 格式化时间间隔:“1 小时 30 分钟”。
using Humanizer;
DateTime pastDate = DateTime.UtcNow.AddHours(-5);Console.WriteLine(pastDate.Humanize()); // "5 小时前"
TimeSpan span = new TimeSpan(2, 45, 0);Console.WriteLine(span.Humanize()); // "2 小时 45 分钟"Humanizer 支持本地化(俄语 — Humanizer.Core.ru)。
5. FluentDateTime — DateTime 的流畅接口
FluentDateTime(NuGet: FluentDateTime)—— 为