1. 操作日期和时间的常见任务
搞日期和时间经常让人有点慌(有时候还挺慌的),就算是老司机程序员也一样。你得比较日期、算间隔、加减天/月/年、算年龄、判断星期几,还有一堆别的事。
这些都是做任务追踪、日历、会员卡或订阅管理、财务计算、统计报表,当然还有面试题(比如“算两个日期之间有多少个工作日”)里常见的需求。
在C#和.NET里,这些事都有内置的类和方法。而且最重要的是——大部分计算都是面向对象的,安全又直观的API来搞定。
2. TimeSpan结构体——测量时间间隔
一切都从TimeSpan结构体开始。它就是“一段”时间,比如5天、3小时、7分钟21秒这种。
怎么创建TimeSpan?
可以“相减”两个日期,也可以直接new出来:
// 两个日期的差值永远是TimeSpan!
DateTime start = new DateTime(2025, 5, 1, 7, 0, 0);
DateTime end = new DateTime(2025, 5, 2, 11, 30, 0);
TimeSpan duration = end - start; // 这就是魔法!
Console.WriteLine(duration); // 1.04:30:00 (1天4小时30分钟)
也可以直接用构造函数参数创建TimeSpan:
TimeSpan span = new TimeSpan(2, 14, 18, 0); // 2天14小时18分钟0秒
Console.WriteLine(span); // 2.14:18:00
还有一种更直观的方式——用静态方法:
TimeSpan fiveMinutes = TimeSpan.FromMinutes(5);
TimeSpan twoHours = TimeSpan.FromHours(2);
TimeSpan oneWeek = TimeSpan.FromDays(7);
TimeSpan有哪些属性?
| 属性 | 说明 |
|---|---|
|
天数(整数) |
|
小时部分 |
|
分钟部分 |
|
秒部分 |
|
总天数(小数) |
|
总小时数(小数) |
|
总分钟数(小数) |
|
总秒数(小数) |
Console.WriteLine($"天数: {duration.Days}, 总小时数: {duration.TotalHours}");
怎么把TimeSpan加到日期上/减去?
DateTime now = DateTime.Now;
DateTime future = now.Add(duration); // 给now加上duration
DateTime past = now.Subtract(TimeSpan.FromDays(10)); // 减去10天
Console.WriteLine(future);
Console.WriteLine(past);
3. 日期计算器:算两个日期的差值
这个技能几乎随时都用得上。比如有人想知道离放假还有多久,有人想知道免费期啥时候结束。
DateTime today = DateTime.Today;
DateTime vacation = new DateTime(2025, 8, 1);
TimeSpan untilVacation = vacation - today;
Console.WriteLine($"离放假还有 {untilVacation.Days} 天!");
注意:如果相减的都是“纯日期”(用DateTime.Date或者DateTime.Today),结果就是整数天。如果有一个带时间,结果就是小数。
int days = (vacation - today).TotalDays; // 编译错误! TotalDays 是 double
如果你想要整数——用.Days或者把(int)TotalDays强转成int。
4. 加减时间:AddDays、AddMonths、AddHours等方法
C#不用你自己算每个月多少天、闰年啥的,直接用方法就行:
DateTime orderDate = new DateTime(2024, 4, 20);
DateTime deliveryDate = orderDate.AddDays(14); // 2周后
Console.WriteLine($"商品将在 {deliveryDate.ToShortDateString()} 送达");
| 方法 | 加什么(负数就是减) |
|---|---|
|
天数(支持小数,比如1.5天) |
|
月数(自动考虑每月天数) |
|
年数(连闰年都算上) |
|
小时 |
|
分钟 |
|
秒 |
DateTime birthday = new DateTime(2000, 2, 29);
DateTime nextYear = birthday.AddYears(1); // 2001-02-28(不是29,因为2001不是闰年)
Console.WriteLine(nextYear.ToShortDateString()); // 28.02.2001
别忘了:所有这些方法都会返回一个新的日期对象,原来的不会变!
var dt = DateTime.Now;
dt.AddDays(5); // 这不会改变dt!
dt = dt.AddDays(5); // 这样才会变
5. 计算用的辅助方法
算星期几
大多数时候直接用.DayOfWeek属性就行:
DateTime examDate = new DateTime(2025, 6, 19);
DayOfWeek day = examDate.DayOfWeek;
Console.WriteLine(day); // Wednesday
也可以转成数字:
int number = (int)day; // Sunday == 0, Monday == 1, 以此类推
判断“今天”、“昨天”、“明天”
最简单的比较:
DateTime date = new DateTime(2025, 6, 18);
if (date.Date == DateTime.Today)
Console.WriteLine("今天!");
else if (date.Date == DateTime.Today.AddDays(-1))
Console.WriteLine("昨天!");
else if (date.Date == DateTime.Today.AddDays(1))
Console.WriteLine("明天!");
算年龄
最常见的需求之一——正确算出人的年龄。直接减年份其实不总是对的:
public static int CalculateAge(DateTime birthDate, DateTime currentDate)
{
int age = currentDate.Year - birthDate.Year;
// 如果今年生日还没到
if (currentDate.Month < birthDate.Month ||
(currentDate.Month == birthDate.Month && currentDate.Day < birthDate.Day))
{
age--;
}
return age;
}
// 用法
DateTime birth = new DateTime(1990, 8, 15);
DateTime today = DateTime.Today;
int age = CalculateAge(birth, today);
Console.WriteLine($"年龄: {age} 岁");
搞定工作日
经常要算两个日期之间有多少个工作日,排除周末:
public static int CountWorkingDays(DateTime startDate, DateTime endDate)
{
int workingDays = 0;
DateTime current = startDate;
while (current <= endDate)
{
if (current.DayOfWeek != DayOfWeek.Saturday &&
current.DayOfWeek != DayOfWeek.Sunday)
{
workingDays++;
}
current = current.AddDays(1);
}
return workingDays;
}
6. 主要类之间的关系
graph TD
A(DateTime) --相减--> B(TimeSpan)
A2(DateTime) --AddDays, AddMonths--> A
A --ToLocalTime/ToUniversalTime--> C(DateTimeOffset)
D(DateOnly) --ToDateTime--> A
E(TimeOnly) --ToTimeSpan--> B
A --DayOfWeek, Day, Month, Year--> F(数字属性)
B(TimeSpan) --TotalDays, TotalHours, ...--> G(持续时间属性)
7. 速查表:如果你想……
| 需求 | 用啥 | 例子 |
|---|---|---|
| 算两个日期的差值 | |
|
| 给日期加2周 | |
|
| 算年龄 | 用和月份/天的判断 |
见上面那节 |
| 只要日期部分 | |
|
| 只要时间部分 | |
|
| 比较日期 | 用、、、 |
|
| 换时区 | |
|
| 查一年中的第几周 | |
看文档 |
| 查星期几 | |
|
| 算工作日 | 循环判断 |
见上面那节 |
GO TO FULL VERSION