楼主: 股式
29 0

C#.NET DateTime 最强入门到进阶:格式化、转换、UTC、时区全覆盖 [推广有奖]

  • 0关注
  • 0粉丝

等待验证会员

学前班

40%

还不是VIP/贵宾

-

威望
0
论坛币
0 个
通用积分
0
学术水平
0 点
热心指数
0 点
信用等级
0 点
经验
20 点
帖子
1
精华
0
在线时间
0 小时
注册时间
2018-10-21
最后登录
2018-10-21

楼主
股式 发表于 2025-11-21 10:51:50 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币

简介

DateTime

在 .NET 框架中,DateTimeSystem 命名空间下用于表示日期与时间的核心结构体,广泛应用于各种时间相关的操作场景,如时间的存储、计算、格式化以及与其他时间格式之间的转换。

System

DateTime 结构概述

定义

System.DateTime

DateTime 是一个值类型(struct),其内部通过“刻度”(ticks)来表示时间点。每个 tick 等于 100 纳秒,从公元 0001 年 1 月 1 日午夜 00:00:00 开始计数。

struct
DateTime.MinValue

内部存储机制

该结构包含两个核心组成部分:

  • 一个 long 类型的 ticks 值,记录自起始时间以来经过的时间单位;
  • 一个 DateTimeKind 枚举值,标识该时间的时区类别:
long
DateTimeKind
  • Unspecified:未明确指定是本地时间还是 UTC 时间;
  • Utc:表示协调世界时(UTC);
  • Local:表示当前系统所在的本地时区时间。
Unspecified
UTC
Utc
Local

支持的时间范围

有效时间跨度为:

  • 最小值:DateTime.MinValue → 0001-01-01 00:00:00
  • 最大值:DateTime.MaxValue → 9999-12-31 23:59:59.9999999
DateTime.MinValue
DateTime.MaxValue

时间单位换算关系

1 秒 = 10,000,000 Ticks  
1 毫秒 = 10,000 Ticks  
1 分钟 = 600,000,000 Ticks

主要功能特性

完整的时间信息表达

DateTime 可精确表示年、月、日、时、分、秒及毫秒,并提供相应属性进行访问。同时支持 Kind 属性以区分时间类型。

Kind
Utc、Local、Unspecified

时间比较与运算

  • 可通过标准比较操作符(如 <, >, ==)对两个 DateTime 实例进行比较;
  • 支持加减时间间隔(使用 AddDays, AddHours, AddMinutes 等方法);
  • 可计算两个时间点之间的时间差,返回 TimeSpan 对象。
Compare、CompareTo
AddDays、AddHours
Subtract
TimeSpan

格式化输出

借助 ToString() 方法和标准或自定义格式字符串,实现灵活的时间格式化显示,例如:

dt.ToString("yyyy-MM-dd HH:mm:ss")
ToString
"yyyy-MM-dd HH:mm:ss"

此外,还支持根据不同的区域性(CultureInfo)进行本地化格式输出。

CultureInfo

数据转换能力

支持与多种时间表示形式相互转换,包括:

  • 字符串解析(Parse, TryParse);
  • Unix 时间戳(以秒或毫秒为单位);
  • 数据库中的日期时间类型。
Unix

常用静态属性

  • DateTime.Now:获取当前本地时间;
  • DateTime.UtcNow:获取当前 UTC 时间;
  • DateTime.Today:获取当前日期,时间部分归零(即 00:00:00)。
DateTime.Now
DateTime.UtcNow
UTC
DateTime.Today

核心属性一览表

Now
UtcNow
Today
Date
Year
Month
Day
Hour
Minute
Second
Millisecond
DayOfWeek
DayOfWeek.Monday
DayOfYear
Kind
Utc
Local
Unspecified
Ticks
属性名 说明
DateTime.Now 返回当前本地时区的日期和时间
DateTime.UtcNow 返回当前的协调世界时(UTC)
DateTime.Today 返回今天的日期,时间设为 00:00:00
Date 提取当前实例的日期部分,时间归零
Year, Month, Day 分别获取年、月、日
Hour, Minute, Second, Millisecond 获取对应的时间组成部分
DayOfWeek 返回星期几的枚举值(如 Monday, Tuesday...)
DayOfYear 返回该日期在当年中的第几天(范围:1–366)
Kind 指示时间种类(Unspecified / Utc / Local)
Ticks 返回自 0001-01-01 00:00:00 起经过的 tick 数(每 tick 为 100ns)

示例代码:

var dt = DateTime.Now;
Console.WriteLine($"{dt.Year}-{dt.Month}-{dt.Day} {dt.Hour}:{dt.Minute}:{dt.Second}, Kind={dt.Kind}");

构造与类型转换

构造函数使用方式

// 指定年月日时分秒
var dt1 = new DateTime(2025, 8, 8, 14, 30, 0);

// 同时指定 DateTimeKind
var dt2 = new DateTime(2025, 8, 8, 14, 30, 0, DateTimeKind.Utc);

// 从 ticks 构造
var dtTicks = new DateTime(637632000000000000L);

与 Unix 时间戳互转

// 将 Unix 时间戳(秒)转换为 DateTime(UTC)
var unixEpoch = DateTimeOffset.FromUnixTimeSeconds(0).UtcDateTime;

// 当前 UTC 时间转为 Unix 时间戳(秒)
long toUnix = ((DateTimeOffset)DateTime.UtcNow).ToUnixTimeSeconds();

与 DateTimeOffset 的交互

DateTimeOffset 更适合处理跨时区应用,因为它不仅包含时间点,还显式保存了相对于 UTC 的偏移量,避免了因 DateTime.Kind 不明确而导致的问题。

DateTimeOffset

推荐在涉及全球化或多时区逻辑时优先使用 DateTimeOffset,而非依赖 DateTimeKind 属性进行推断。

Kind

从 DateTime 转换为 DateTimeOffset

var dto = new DateTimeOffset(dt);              // 使用本地时区偏移
var dtoUtc = new DateTimeOffset(dt, TimeSpan.Zero); // 强制设置为 UTC 偏移
DateTime

特殊日期常量获取

DateTime today = DateTime.Today; // 获取今日零点时间
DateTime min = DateTime.MinValue; // 最小时间值(0001-01-01)
DateTime max = DateTime.MaxValue; // 最大时间值(9999-12-31)
DateTime unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); // Unix 时间起点

DateTimeKind 枚举与时区处理

枚举定义

public enum DateTimeKind
{
    Unspecified = 0, // 未指定时区(默认值)
    Utc         = 1, // 表示 UTC 时间
    Local       = 2  // 表示本地时区时间
}

正确设置 Kind 对于避免时区混淆至关重要,特别是在序列化、反序列化或跨系统传递时间数据时。

日期时间组件访问

通过 DateTime 对象的属性,可以方便地获取时间的各个组成部分:

DateTime dt = new DateTime(2023, 10, 5, 14, 30, 45, 123);
int year = dt.Year;           // 2023
int month = dt.Month;         // 10
int day = dt.Day;             // 5
int hour = dt.Hour;           // 14
int minute = dt.Minute;       // 30
int second = dt.Second;       // 45
int millisecond = dt.Millisecond; // 123
long ticks = dt.Ticks;        // 638,000,000,000,000,000 + ...

格式化与解析

标准格式化字符串

格式符说明示例输出
"d"短日期2023-06-15
"D"长日期2023年6月15日
"t"短时间14:30
"T"长时间14:30:45
"f"完整日期/时间2023年6月15日 14:30
"F"完整格式2023年6月15日 14:30:45
"g"常规短格式2023-06-15 14:30
"G"常规长格式2023-06-15 14:30:45
"s"可排序格式2023-06-15T14:30:45
"u"通用可排序2023-06-15 14:30:45Z
"U"UTC完整格式2023年6月15日 6:30:45

标准格式化示例

dt.ToString("o");  // ISO 8601 完整格式:2025-08-08T14:30:00.0000000Z
dt.ToString("s");  // 可排序格式:2025-08-08T14:30:00
dt.ToString("G");  // 默认长日期+长时间
dt.ToString("d");  // "2023/10/1"(短日期)
dt.ToString("D");  // "2023年10月1日"(长日期)
dt.ToString("t");  // "14:30"(短时间)
dt.ToString("T");  // "14:30:00"(长时间)

自定义格式化

dt.ToString("yyyy-MM-dd HH:mm:ss");      // 2025-08-08 14:30:00
dt.ToString("yyyy-MM-dd HH:mm:ss.fff");  // 带毫秒
dt.ToString("dddd, MMM d yyyy");         // 星期几, 月 日 年

时间解析操作

使用 .NET 提供的方法可以从字符串还原为 DateTime 对象。

Parse / TryParse
DateTime.Parse("2025-08-08 14:30");
DateTime.TryParse("2025-08-08", out var dt);

指定格式解析

DateTime.ParseExact("08/08/2025", "MM/dd/yyyy", CultureInfo.InvariantCulture);
DateTime.TryParseExact(input, new[] { "yyyy-MM-dd", "MM/dd/yyyy" },
                       CultureInfo.InvariantCulture, DateTimeStyles.None, out dt);

时区转换最佳实践

在处理跨时区应用时,正确管理时区信息至关重要。以下是一些常见操作的实现方式:

Local = 2        // 本地时间
}
// 创建包含时区信息的时间实例
DateTime utcTime = new DateTime(2023, 10, 1, 0, 0, 0, DateTimeKind.Utc);
DateTime localTime = new DateTime(2023, 10, 1, 8, 0, 0, DateTimeKind.Local);

// 获取目标时区(例如中国标准时间)
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("China Standard Time");

// 将 UTC 时间转换为中国标准时间
DateTime utcToChina = TimeZoneInfo.ConvertTimeFromUtc(utcTime, tz);

// 将本地时间转换为 UTC 时间
DateTime chinaToUtc = TimeZoneInfo.ConvertTimeToUtc(localTime, tz);

// 跨时区转换:从中国时间转为美国东部时间
TimeZoneInfo nyTz = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTime chinaToNy = TimeZoneInfo.ConvertTime(localTime, tz, nyTz);

日期计算辅助

在处理日期时,.NET 提供了多种方法来获取特定信息。例如:

DateTime dt = new DateTime(2023, 2, 15);
// 获取指定月份的天数
int daysInFeb = DateTime.DaysInMonth(2023, 2); // 结果为 28
// 判断是否为闰年
bool isLeap2023 = DateTime.IsLeapYear(2023); // false
bool isLeap2024 = DateTime.IsLeapYear(2024); // true
// 获取当月的第一天和最后一天
DateTime firstDayOfMonth = new DateTime(dt.Year, dt.Month, 1);
DateTime lastDayOfMonth = new DateTime(dt.Year, dt.Month,
    DateTime.DaysInMonth(dt.Year, dt.Month));

时间与日期的基本属性提取

可以从一个 DateTime 实例中提取出星期几、一年中的第几天等信息:

DayOfWeek dayOfWeek = dt.DayOfWeek; // DayOfWeek.Thursday
int dayOfYear = dt.DayOfYear;       // 278(表示2023年10月5日是该年的第278天)

日期时间的运算与比较

算术操作

支持对时间进行加减操作,包括天数、小时、分钟等单位:

DateTime now = DateTime.Now;
// 加法示例
DateTime tomorrow = now.AddDays(1);
DateTime nextHour = now.AddHours(1);
DateTime nextMinute = now.AddMinutes(1);
// 减法示例
DateTime yesterday = now.AddDays(-1);
DateTime lastWeek = now.AddDays(-7);

还可以通过 Ticks 进行更高精度的操作:

// 增加5毫秒(每毫秒等于10,000个Ticks)
DateTime preciseTime = now.AddTicks(50000);

计算两个日期之间的时间跨度:

DateTime start = new DateTime(2023, 1, 1);
DateTime end = new DateTime(2023, 12, 31);
TimeSpan duration = end - start; // 相差364天

比较操作

可以使用 Compare 方法或重载的操作符来进行日期比较:

DateTime dateA = new DateTime(2023, 6, 15);
DateTime dateB = new DateTime(2023, 6, 20);
// 使用静态 Compare 方法
int compareResult = DateTime.Compare(dateA, dateB);
// 返回值说明:
// <0 表示 dateA 在 dateB 之前
// =0 表示两者相等
// >0 表示 dateA 在 dateB 之后

// 使用操作符进行直观判断
bool isBefore = dateA < dateB;   // true
bool isAfter = dateA > dateB;    // false
bool isSame = dateA == dateB;    // false

// 检查是否在某个时间范围内
bool isInRange = dateA >= start && dateA <= end;

DateTime 与其他时间类型的对比分析

特性 DateTime DateTimeOffset TimeOnly DateOnly NodaTime
时区支持 强(含偏移量)
日期部分 需要计算提取 需要计算提取
时间部分
精度 100纳秒 100纳秒 100纳秒 天级 1纳秒
序列化安全性 存在问题 安全 安全 安全 安全
有效范围 0001-9999年 0001-9999年 00:00-24:00 0001-9999年 无限
.NET 版本要求 1.0+ 2.0+ 6.0+ 6.0+ NuGet 包

最佳实践建议

存储原则

推荐始终以 UTC 时间进行数据存储,在展示给用户时再转换为本地时间。

UTC

序列化规范

为确保跨平台兼容性,建议使用 ISO 8601 标准格式进行序列化:

// 示例:输出标准UTC时间字符串
DateTime.UtcNow.ToString("O"); // 如:2023-10-05T06:30:45.1234567Z

时区处理策略

对于简单的时区偏移场景,应优先使用:

DateTimeOffset

替代传统的不带偏移量类型:

DateTime

若涉及复杂的时区规则(如夏令时),推荐采用:

NodaTime
TimeZoneInfo

日期与时间分离设计

从 .NET 6 开始,可利用新引入的类型实现更清晰的数据建模:

// 推荐方式
DateOnly birthday = new DateOnly(1990, 5, 15);
TimeOnly meetingTime = new TimeOnly(14, 30);

性能优化建议

在性能敏感的应用中,避免频繁调用某些高开销方法:

DateTime.Now/UtcNow

建议将固定日期值预先计算并缓存为静态变量。

对于极高精度的计时需求,应使用专门的高精度计时机制:

Stopwatch

参考资料与官方文档

DateTime
:https://learn.microsoft.com/en-us/dotnet/api/system.datetime
TimeZoneInfo

ASP.NET Core 是一个开源的高性能框架,用于构建现代云端集成的应用程序。它支持跨平台开发,允许开发者在 Windows、Linux 和 macOS 上构建和运行应用。该框架适用于微服务架构、Web 应用、API 以及实时通信应用等多种场景。

通过 ASP.NET Core,开发者可以利用依赖注入、配置管理、日志记录等内置功能,提升开发效率并增强应用的可维护性。此外,它与 .NET 运行时深度集成,能够充分发挥 .NET 生态系统的优势。

ASP.NET Core

System.TimeZoneInfo 类是 .NET 中用于表示任意时区的时间信息的类。它提供了将时间在不同时区之间进行转换的能力,支持夏令时规则,并允许应用程序处理全球范围内的本地时间。该类可用于获取系统已定义的时区,也可创建自定义时区。

开发者可以通过 TimeZoneInfo.FindSystemTimeZoneById 方法根据 ID 获取特定时区,并使用 ConvertTime 方法实现时间的跨时区转换。此功能对于需要处理多地区用户时间数据的应用(如日历、调度系统)尤为重要。

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:datetime date ATET time NET

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
jg-xs1
拉您进交流群
GMT+8, 2025-12-26 22:55