CodeGym /课程 /C# SELF /日期和时间的计算以及辅助类

日期和时间的计算以及辅助类

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

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有哪些属性?

属性 说明
Days
天数(整数)
Hours
小时部分
Minutes
分钟部分
Seconds
秒部分
TotalDays
总天数(小数)
TotalHours
总小时数(小数)
TotalMinutes
总分钟数(小数)
TotalSeconds
总秒数(小数)
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. 加减时间:AddDaysAddMonthsAddHours等方法

C#不用你自己算每个月多少天、闰年啥的,直接用方法就行:

DateTime orderDate = new DateTime(2024, 4, 20);
DateTime deliveryDate = orderDate.AddDays(14); // 2周后

Console.WriteLine($"商品将在 {deliveryDate.ToShortDateString()} 送达");
方法 加什么(负数就是减)
AddDays(double)
天数(支持小数,比如1.5天)
AddMonths(int)
月数(自动考虑每月天数)
AddYears(int)
年数(连闰年都算上)
AddHours(double)
小时
AddMinutes(double)
分钟
AddSeconds(double)
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. 速查表:如果你想……

需求 用啥 例子
算两个日期的差值
TimeSpan duration = d2 - d1
(d2 - d1).Days
给日期加2周
date.AddDays(14)
date.AddDays(14)
算年龄
.Year
和月份/天的判断
见上面那节
只要日期部分
DateOnly
DateOnly.FromDateTime(DateTime.Now)
只要时间部分
TimeOnly
TimeOnly.FromDateTime(DateTime.Now)
比较日期
<
>
==
.CompareTo()
if (d1 < d2) ...
换时区
DateTimeOffset + ToOffset
dto.ToOffset(TimeSpan.FromHours(3))
查一年中的第几周
Calendar.GetWeekOfYear()
看文档
查星期几
date.DayOfWeek
算工作日 循环判断
DayOfWeek
见上面那节
1
调查/小测验
和日期打交道第 15 级,课程 4
不可用
和日期打交道
和日期、时间还有时区打交道
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION