CodeGym /课程 /C# SELF /实用类型:DateOnly 和 TimeOnly

实用类型:DateOnly 和 TimeOnly

C# SELF
第 15 级 , 课程 1
可用

1. 入门

以前在 C# 里没有专门只存日期或者只存时间的类型。所以,就算你只想存个日期——比如生日——也得用 DateTime,还得加个“默认时间”。以前只存日期的老办法就是用 DateTime


DateTime birthday = new DateTime(1985, 4, 20); // 1985年4月20日,00:00:00

但这样其实挺麻烦的。你明明只想要个日期,结果还带了个时间——虽然是零点,但还是会让人懵圈:比如你比较日期的时候,程序可能会把时间也算进去,结果就很迷。

反过来也一样:如果你只关心时间(比如工作时间 08:0017:00),你还得“编”个日期,其实根本没必要。

现在 .NET 里有了专门的 DateOnlyTimeOnly,这些类型直接帮你解决这些乱七八糟的事。

新出的实用类型 DateOnlyTimeOnly

  • DateOnly —— 只存日历日期,没有时间,也没有时区信息。
  • TimeOnly —— 只存一天里的时间,没有年、月、日,也没有时区。

时间类型对比表

类型 日期 时间 时区 用来干啥?
DateTime
🚫 几乎啥都能用(但不总是方便和安全)
DateTimeOffset
需要时间点和时区的时候
DateOnly
🚫 🚫 生日、只要日期不要时间的场景
TimeOnly
🚫 🚫 营业时间、日程表、一天内的时间段

2. 玩转 DateOnly

声明和创建

创建 DateOnly 对象就像养成新习惯一样简单!比如:

// 年,月,日
DateOnly birthday = new DateOnly(1985, 4, 20);
DateOnly 创建生日日期

如果你已经有了 DateTime 对象,可以用 DateOnly.FromDateTime

DateTime now = DateTime.Now;
DateOnly today = DateOnly.FromDateTime(now);
// 现在 today 只包含日期,时间被扔掉了

常用属性和方法

  • YearMonthDay —— 跟 DateTime 一样用法。
  • .ToString() —— 格式化日期,可以自定义格式。
Console.WriteLine($"生日:{birthday.Year}年,{birthday.Month}月,{birthday.Day}日。");

Console.WriteLine(today.ToString("dd.MM.yyyy")); // 比如 30.07.2024

日期运算

可以很方便地加天/加月/加年:

DateOnly tomorrow = today.AddDays(1);
DateOnly nextMonth = today.AddMonths(1);

试试在你的主项目里,把只存日期的 DateTime 字段都换成 DateOnly —— 你就离现代 .NET 更近一步啦!

日期比较

可以直接用 <>== 来比较:

if (birthday < today)
    Console.WriteLine("生日已经过了,或者很久以前就过了 :)");

再也不会被多余的毫秒、分钟坑了。

获取今天的日期

DateOnly currentDate = DateOnly.FromDateTime(DateTime.Now);

3. 玩转 TimeOnly

现在来聊聊只存时间不带日期——哪个程序员没遇到过午饭时间表啊?

创建 TimeOnly

TimeOnly startWork = new TimeOnly(9, 0);    // 09:00
TimeOnly endWork = new TimeOnly(17, 30);    // 17:30

可以只拿小时、分钟、秒:

Console.WriteLine($"工作时间:从 {startWork.Hour}:{startWork.Minute:D2} 到 {endWork.Hour}:{endWork.Minute:D2}");

DateTime 获取时间

DateTime now = DateTime.Now;
TimeOnly currentTime = TimeOnly.FromDateTime(now);
Console.WriteLine($"现在是 {currentTime}");

时间运算

TimeOnly breakStart = startWork.AddHours(4); // 4小时后休息,也就是13:00
TimeOnly breakEnd = breakStart.AddMinutes(30); // 午饭30分钟

比较和判断

if (currentTime >= startWork && currentTime <= endWork)
    Console.WriteLine("该工作啦 :)");
else
    Console.WriteLine("可以休息了。");

4. 和其他类型的互动

DateOnlyTimeOnlyDateTime 之间的转换

有时候你还得把它们合成 DateTime(比如老数据库要存,或者要兼容):


DateOnly datePart = new DateOnly(2024, 7, 30);
TimeOnly timePart = new TimeOnly(14, 15);
DateTime datetime = datePart.ToDateTime(timePart); // 2024-07-30 14:15:00

反过来也可以:

DateTime dt = DateTime.Now;
DateOnly justDate = DateOnly.FromDateTime(dt);
TimeOnly justTime = TimeOnly.FromDateTime(dt);

重要细节和常见坑

  • 如果你用老方法 DateTime.Parse() 去解析只有日期或只有时间的字符串,大概率会报错或者结果不对。遇到这种情况要用专门的方法:DateOnly.Parse()TimeOnly.Parse() —— 它们知道怎么处理“只要一半”的值。
  • 注意:DateOnlyTimeOnly 完全不知道啥是时区。它们就是单纯的日期或者时间——跟时区没半毛钱关系。如果你要考虑时区,得自己单独存这玩意儿。
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION