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

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

时间:2026-08-27  |  作者:风起客  |  阅读:0

目录

  1. 简介
  2. DateTime 结构概述
  3. 主要功能
  4. 表示日期和时间:
  5. 时间操作:
  6. 格式化:
DateTime 结构概述 对应的技术说明图
DateTime 结构概述概括DateTime 结构概述的核心概念、关键要点与实践提示。
简介 对应的技术说明图
简介概括简介的核心概念、关键要点与实践提示。

前言

在 C# 开发中,System.DateTime 是处理时间相关操作的核心结构体。作为值类型,它通过存储自公元 0001 年 1 月 1 日以来的刻度数来精确表示时间,并借助 DateTimeKind 枚举区分本地、UTC 或未指定状态。掌握其内部存储机制与范围,是进行高效时间计算、格式转换及时区处理的基础,本文深入解析其关键特性与实用技巧。

C#.NET DateTime 最强入门到进阶:格式化、转换、UTC、时区全覆盖 的核心流程信息图
C#.NET DateTime 最强入门到进用简体中文信息图概括C#.NET DateTime 最强入门到进的核心流程、关键规则与实践要点。

简介

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

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)

// 时间单位转换
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 对象转换为字符串,或者从字符串解析为 DateTime 对象。

  • 处理时区转换时,需注意 DateTime.Now 和 DateTime.UtcNow 的区别,确保时间数据的准确性。

  • 对于需要高精度时间处理的场景,UTC 提供了更细粒度的控制能力。

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

静态属性:

  • DateTime.Now:本地时间。

  • DateTime.UtcNow:UTC 时间。

  • 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 为单位)
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);

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

从 ticks

var dtTicks = new DateTime(637632000000000000L);

与 Unix 时间戳

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

与 DateTimeOffset

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

  • 从 DateTime 转换:

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

特殊日期获取

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 枚举

public enum DateTimeKind
{
    Unspecified = 0, // 未指定时区(默认)
    Utc = 1,         // UTC时间
    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);

格式化与解析

标准格式化字符串

格式符说明示例输出
"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");         // 星期几, 月 日 年

解析

  • 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);

日期时间组件访问

属性访问

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天)

日期计算辅助

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 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毫秒

比较操作

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 与相关类型对比

最佳实践总结

存储原则:

  • 始终以 UTC 时间存储

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

序列化准则:

// 使用ISO 8601格式
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

资源和文档

特性DateTimeDateTimeOffsetTimeOnlyDateOnlyNodaTime
时区支持弱强(偏移量)无无强
日期部分需要计算需要计算无有有
时间部分有有有无有
精度100ns100ns100ns天1ns
序列化有问题安全安全安全安全
范围0001-99990001-999900:00-24:000001-9999无限
.NET版本1.0+2.0+6.0+6.0+NuGet包

免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。

相关文章

更多

精选合集

更多

大家都在玩

热门话题

大家都在看

更多