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

简介

DateTimeSystem 命名空间中用于表示日期和时间的结构体,广泛用于处理时间相关的操作,如存储、计算、格式化等。

DateTime 结构概述

  • 定义:System.DateTime 是一个值类型(struct),表示自公元 0001 年 1 月 1 日午夜 00:00:00(DateTime.MinValue)起经过的"刻度"(ticks,1 tick = 100 纳秒)数。

  • 内部存储:一个 long 值(ticks)+ 一个 DateTimeKind 枚举,指示时间的"种类":

    • Unspecified:未指定是本地还是 UTC

    • Utc:协调世界时

    • Local:本地时区时间

  • 范围:DateTime.MinValue(0001-01-01),DateTime.MaxValue(9999-12-31 23:59:59.9999999)

csharp 复制代码
// 时间单位转换
1 秒 = 10,000,000 Ticks
1 毫秒 = 10,000 Ticks
1 分钟 = 600,000,000 Ticks

主要功能

表示日期和时间:

  • 包含年、月、日、时、分、秒、毫秒。

  • 支持 Kind 属性(Utc、Local、Unspecified)。

时间操作:

  • 比较:Compare、CompareTo

  • 运算:加减时间(AddDays、AddHours 等)。

  • 时间差:Subtract 返回 TimeSpan

格式化:

  • 使用 ToString 格式化(如 "yyyy-MM-dd HH:mm:ss")。

  • 支持区域性(CultureInfo)。

转换:

  • 与字符串、Unix 时间戳、数据库时间互转。

静态属性:

  • DateTime.Now:本地时间。

  • DateTime.UtcNowUTC 时间。

  • DateTime.Today:当前日期(时间为 00:00:00)。

核心属性

属性 说明
Now 返回本地时区当前时间
UtcNow 返回 UTC 当前时间
Today 返回本地时区当前日期(00:00:00 时分秒)
Date 取当前实例的日期部分,时间部分置 00:00:00
Year, Month, Day 年、月、日
Hour, Minute, Second, Millisecond 小时、分钟、秒、毫秒
DayOfWeek 星期枚举(DayOfWeek.Monday...)
DayOfYear 年内天数(1--366)
Kind 时间种类(Utc/Local/Unspecified
Ticks 自 0001-01-01 00:00:00 起的刻度数(100ns 为单位)
csharp 复制代码
var dt = DateTime.Now;
Console.WriteLine($"{dt.Year}-{dt.Month}-{dt.Day} {dt.Hour}:{dt.Minute}:{dt.Second}, Kind={dt.Kind}");

构造与转换

构造器

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

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

从 ticks

csharp 复制代码
var dtTicks = new DateTime(637632000000000000L);

与 Unix 时间戳

csharp 复制代码
// DateTime <-> Unix seconds
var unixEpoch = DateTimeOffset.FromUnixTimeSeconds(0).UtcDateTime;
long toUnix = ((DateTimeOffset)DateTime.UtcNow).ToUnixTimeSeconds();

与 DateTimeOffset

  • DateTimeOffset 推荐用于跨时区场景,包含一个偏移量字段,且不朴素依赖 Kind

  • DateTime 转换:

csharp 复制代码
var dto = new DateTimeOffset(dt);              // 按本地偏移
var dtoUtc = new DateTimeOffset(dt, TimeSpan.Zero);

特殊日期获取

csharp 复制代码
DateTime today = DateTime.Today; // 今天的午夜时间
DateTime min = DateTime.MinValue;
DateTime max = DateTime.MaxValue;
DateTime unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

DateTimeKind 与时区处理

DateTimeKind 枚举

csharp 复制代码
public enum DateTimeKind
{
    Unspecified = 0, // 未指定时区(默认)
    Utc = 1,         // UTC时间
    Local = 2        // 本地时间
}

时区转换最佳实践

csharp 复制代码
// 创建带时区信息的时间
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);

格式化与解析

标准格式化字符串

格式符 说明 示例输出
"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

格式化

  • 标准格式
csharp 复制代码
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"(长时间)
  • 自定义格式
csharp 复制代码
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");         // 星期几, 月 日 年

解析

  • Parse / TryParse
csharp 复制代码
DateTime.Parse("2025-08-08 14:30");
DateTime.TryParse("2025-08-08", out var dt);
  • 指定格式解析
csharp 复制代码
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);

日期时间组件访问

属性访问

csharp 复制代码
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 + ...

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

日期计算辅助

csharp 复制代码
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));

日期时间运算与比较

算术运算

csharp 复制代码
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);

// 时间跨度计算
DateTime start = new DateTime(2023, 1, 1);
DateTime end = new DateTime(2023, 12, 31);
TimeSpan duration = end - start; // 364天

// Ticks运算
DateTime preciseTime = now.AddTicks(50000); // 增加5毫秒

比较操作

csharp 复制代码
DateTime dateA = new DateTime(2023, 6, 15);
DateTime dateB = new DateTime(2023, 6, 20);

// 比较方法
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
时区支持 强(偏移量)
日期部分 需要计算 需要计算
时间部分
精度 100ns 100ns 100ns 1ns
序列化 有问题 安全 安全 安全 安全
范围 0001-9999 0001-9999 00:00-24:00 0001-9999 无限
.NET版本 1.0+ 2.0+ 6.0+ 6.0+ NuGet包

最佳实践总结

存储原则:

  • 始终以 UTC 时间存储

  • 仅在显示时转换为本地时间

序列化准则:

csharp 复制代码
// 使用ISO 8601格式
DateTime.UtcNow.ToString("O"); // 2023-10-05T06:30:45.1234567Z

时区处理:

  • 使用 DateTimeOffset 替代 DateTime

  • 复杂时区需求使用 NodaTimeTimeZoneInfo

日期/时间分离:

csharp 复制代码
// .NET 6+ 推荐
DateOnly birthday = new DateOnly(1990, 5, 15);
TimeOnly meetingTime = new TimeOnly(14, 30);

性能敏感场景:

  • 避免重复调用 DateTime.Now/UtcNow

  • 预计算静态日期值

  • 高精度计时用 Stopwatch

资源和文档

相关推荐
追逐时光者13 小时前
快速构建一个基础、现代化的 WinForm 管理系统
后端·.net
葛小白116 小时前
C#进阶13:C#全局路径规划算法_A*
c#·路径规划算法·astar算法
时光追逐者19 小时前
C#/.NET/.NET Core技术前沿周刊 | 第 61 期(2025年11.10-11.16)
c#·.net·.netcore
2509_9408802220 小时前
【update 更新数据语法合集】.NET开源ORM框架 SqlSugar 系列
开源·.net
世洋Blog21 小时前
Unity面经-List底层原理、如何基于数组、如何扩容、List存储泛型、List有关在内存中的结构
unity·面试·c#·list
PfCoder1 天前
C# async / await 用法以及和Task的关系
c#·多线程·winform·async、await
葛小白11 天前
Labview实用04:Labview调用.net中的事件
.net·labview