C# 中的 DateTime

在 .NET 开发中,DateTime 是我们最常用的结构之一,用于表示一个具体的日期和时间点。无论是记录创建时间、判断是否过期,还是做定时任务,都绕不开它。


一、DateTime 是什么?

复制代码
public struct DateTime : IComparable, IFormattable, IConvertible, ISerializable, IComparable<DateTime>, IEquatable<DateTime>
  • DateTime 是一个结构体,表示一个精确到 100 纳秒的时间点

  • 它的最小值是 0001-01-01 00:00:00,最大值是 9999-12-31 23:59:59

  • 一秒等于十亿纳秒(10,0000,0000)


二、常用获取方式

1. 获取当前本地时间

复制代码
DateTime now = DateTime.Now;
  • Now 返回当前系统的本地时间,受时区影响。

  • 依赖操作系统的时钟。

2. 获取当前 UTC 时间

复制代码
DateTime utcNow = DateTime.UtcNow;
  • UtcNow 返回协调世界时(UTC),不受本地时区影响。

  • 是跨地区应用推荐使用的时间源。

3. 今天零点

复制代码
DateTime today = DateTime.Today; // 今天 00:00:00

三、Now 和 UtcNow 的区别

特性 DateTime.Now DateTime.UtcNow
是否受时区影响
显示是否直观 是(适合用户界面)
跨时区是否安全
用于日志存储 不推荐 推荐

建议:计算和存储用 UtcNow,展示给用户时再转为本地时间。


四、Ticks

1.什么是 Tick?

在 .NET 中:

1 Tick = 100 纳秒(即 0.0000001 秒)

这意味着:

  • 1 毫秒 = 10,000 ticks

  • 1 秒 = 10,000,000 ticks(十亿除以一百得到一千万,可以打印 DateTime.MinValue.AddSeconds(1).Ticks验证)

DateTime.Ticks 是一个 long 类型,表示自 0001-01-01 00:00:00(公元 1 年 1 月 1 日)以来经过的 Tick 数。

cs 复制代码
DateTime dt = new DateTime(2025, 8, 7);
Console.WriteLine(dt.Ticks); // 输出:638536704000000000(具体数值因时间不同而变化)

2.DateTime.MaxValue 的极限是多少?

在 .NET 中,DateTime 的最大值是:

复制代码
DateTime max = DateTime.MaxValue;
Console.WriteLine(max); // 9999-12-31 23:59:59.9999999
Console.WriteLine(max.Ticks); // 3155378975999999999

换句话说,DateTime 可以精确表示的最晚时刻是:

复制代码
9999-12-31 23:59:59.9999999(共 7 位小数,单位是 100 纳秒)

这个时间点的 Ticks 值是 3,155,378,975,999,999,999,也就是自公元 0001 年 1 月 1 日 00:00:00 起,经过的 100 纳秒单位的总数

虽然这个值已经很大,但它只是 long.MaxValue 的约 34% 左右(long.MaxValue9,223,372,036,854,775,807),因此仍有非常大的冗余空间,不会发生溢出。


3.为什么选择 9999 年?

这是出于兼容性和文化意义的考虑:

  • 很多数据库(如 SQL Server)同样以 9999 年为上限。

  • 人类可预见范围内的日期都可以包含。

  • 如果允许更大年份,会影响解析、显示、格式化的性能与实现。


4.小结

属性
最小时间 0001-01-01 00:00:00.0000000
最大时间 9999-12-31 23:59:59.9999999
每 Tick 间隔 100 纳秒(0.0000001 秒)
最大 Ticks 值 3155378975999999999
Ticks 类型 long(Int64)
是否撑爆了? 没有。离爆炸还差得远。

五、系统时间是从哪来的?

1.操作系统维护的系统时钟

DateTime.NowDateTime.UtcNow 都来自操作系统:

  • Windows 会维护一个系统时间(通常为 UTC),并通过 API 提供本地时间或 UTC。

  • 这个系统时间来源于:

    • 主板上的实时时钟(RTC)

    • 网络时间同步(NTP)

    • 用户手动修改

也就是说,可以通过手动或编程方式修改系统时间,影响 DateTime 的表现。

2.更改系统时间:

  • 控制面板 → 日期和时间 → 更改时间(手动)

  • 使用代码(需要管理员权限)调用 SetSystemTime API

  • Linux 系统用 date 命令:sudo date -s "2025-08-07 12:00:00"

例如 C# 调用 API 修改系统时间:

复制代码
[DllImport("kernel32.dll")]
static extern bool SetSystemTime(ref SYSTEMTIME st);

修改系统时间会影响所有基于 DateTime.Now 的逻辑,包括任务调度、日志记录、缓存过期、证书验证等。


六、DateTime 常用 API

🕒 1. 获取当前时间

复制代码
DateTime now = DateTime.Now;       // 本地时间
DateTime utcNow = DateTime.UtcNow; // UTC 时间
DateTime today = DateTime.Today;   // 当天 00:00:00

🏗 2. 构造 DateTime

复制代码
var dt1 = new DateTime(2025, 8, 7); // 只指定日期,时间默认为 00:00:00
var dt2 = new DateTime(2025, 8, 7, 14, 30, 0); // 精确到时分秒

📅 3. 获取组成部分

复制代码
int year = dt2.Year;
int month = dt2.Month;
int day = dt2.Day;
int hour = dt2.Hour;
int minute = dt2.Minute;
int second = dt2.Second;
DayOfWeek dayOfWeek = dt2.DayOfWeek;// 返回表示星期几的枚举值(如 DayOfWeek.Monday)
int dayOfYear = dt2.DayOfYear;// 返回该日期是一年中的第几天(范围 1 ~ 366)
TimeSpan timeOfDay=dt2.TimeOfDay;//返回一个时间间隔,意思是今天已经过了多久

一打印dayOfYear,忽然发现2025一眨眼就过了200多天了 忽忽悠悠今年又快过去了!


➕ 4. 加减时间

复制代码
DateTime tomorrow = DateTime.Now.AddDays(1);
DateTime nextMonth = DateTime.Now.AddMonths(1);
DateTime oneHourLater = DateTime.Now.AddHours(1);
DateTime fiveMinutesAgo = DateTime.Now.AddMinutes(-5);

⏱ 5. 计算时间差(TimeSpan)

复制代码
TimeSpan diff = dt2 - dt1;
double totalDays = diff.TotalDays;
double totalSeconds = diff.TotalSeconds;

🔁 6. 比较时间

复制代码
bool isEarlier = dt1 < dt2;
bool isSame = dt1 == dt2;

int result = DateTime.Compare(dt1, dt2);
// result < 0 表示 dt1 早于 dt2
// result == 0 表示相等
// result > 0 表示 dt1 晚于 dt2

🔤 7. 格式化时间字符串

复制代码
string s1 = dt1.ToString("yyyy-MM-dd"); // 2025-08-07
string s2 = dt1.ToString("yyyy-MM-dd HH:mm:ss"); // 2025-08-07 00:00:00
string s3 = dt1.ToString("dddd"); // 星期几
cs 复制代码
 DateTime currentDateTime = DateTime.Now;
 var culture = new CultureInfo("zh-CN");
 string formattedDate = currentDateTime.ToString("yyyy年M月d日 dddd HH:mm:ss", culture);

注意:格式字符串是区分大小写的。


📥 8. 解析时间字符串

复制代码
DateTime parsed = DateTime.Parse("2025-08-07");
DateTime parsed2 = DateTime.ParseExact("07-08-2025", "dd-MM-yyyy", null);
bool success = DateTime.TryParse("invalid", out DateTime dt); // 不抛异常

🧮 9. 其他有用属性

复制代码
bool isLeapYear = DateTime.IsLeapYear(2024); // 闰年判断
int daysInMonth = DateTime.DaysInMonth(2025, 2); // 某月天数

🔢 10. 时间戳转换(Unix 时间)

复制代码
DateTimeOffset dto = DateTimeOffset.UtcNow;
long unixTimestamp = dto.ToUnixTimeSeconds(); // 秒级时间戳
long millis = dto.ToUnixTimeMilliseconds();   // 毫秒级时间戳

DateTimeOffset fromUnix = DateTimeOffset.FromUnixTimeSeconds(unixTimestamp);

📚 11. Ticks 与精度

复制代码
long ticks = dt1.Ticks; // 100 纳秒为单位的"时间刻度"
DateTime fromTicks = new DateTime(ticks);

延伸阅读

相关推荐
mailtolaozhao3 小时前
C#入门--Hello world
开发语言·c#
重生之我是Java开发战士3 小时前
【C语言】文件操作全解析
c语言·开发语言
驾驭人生3 小时前
C#中统计某个字符出现次数的最简单方法
c#
lishuangquan19877 小时前
在ubuntu上使用jenkins部署.net8程序
ubuntu·jenkins·.net
歪歪1008 小时前
HTML 如何转 Markdown
开发语言·chrome·python·程序人生·html
小坏坏的大世界8 小时前
C++中多线程和互斥锁的基本使用
开发语言·c++
路由侠内网穿透9 小时前
本地部署 SQLite 数据库管理工具 SQLite Browser ( Web ) 并实现外部访问
运维·服务器·开发语言·前端·数据库·sqlite
王者鳜錸9 小时前
PYTHON从入门到实践-18Django模版渲染
开发语言·python·django
Hard but lovely9 小时前
C++ STL--> vector的模拟实现!
开发语言·c++