任何语言,框架,和日期时间相关的知识点就三大块:
前两个知识点,我们已经通过2个章节讲解完毕了,接下来就是时区了。
TimeZoneInfo 类
ASP.NET Core 或者说 C# 中和时区相关的逻辑都封装在 System 命名空间下的 TimeZoneInfo 类中。
TimeZoneInfo 类的实例有以下属性
| 属性 | 说明 | 范例 | 
|---|---|---|
Id | 
时区唯一编号 | Asia/Shanghai | 
BaseUtcOffset | 
与格林威治时间(UTC)之间的时间偏移|08:00:00 | 
|
DaylightName | 
时区的夏令时的显示名称 | China Daylight Time | 
DisplayName | 
时区友好可读名称 | (UTC+08:00) China Standard Time | 
StandardName | 
时区的名称 | China Standard Time | 
SupportsDaylightSavingTime | 
是否支持夏令时 | True | 
最重要的属性有2个 Id 和 BaseUtcOffset,前者关系到时区的获取,或者关系到本地时间和 UTC 时间的偏差。
最最重要的事情
为了简化使用,TimeZoneInfo 有两个静态的属性 TimeZoneInfo.Utc 和 TimeZoneInfo.Local 分别用于表示格林威治时区 (+0UTC) 和本地时区
using System; namespace datetime { class Program { static void Main(string[] args) { Console.WriteLine(TimeZoneInfo.Utc); Console.WriteLine(TimeZoneInfo.Local); } } }
输出结果如下
(UTC) Coordinated Universal Time (UTC+08:00) China Standard Time
获取所有时区和时间偏移 TimeZoneInfo.GetSystemTimeZones()
TimeZoneInfo.GetSystemTimeZones() 返回所有支持的时区列表
using System; namespace datetime { class Program { static void Main(string[] args) { var tzi = TimeZoneInfo.GetSystemTimeZones(); foreach (var tz in tzi) { Console.WriteLine(tz); } } } }
运行结果如下
// 以上忽略 (UTC+08:00) Australian Western Standard Time (UTC+08:00) Brunei Darussalam Time (UTC+08:00) Central Indonesia Time (UTC+08:00) China Standard Time (UTC+08:00) China Standard Time (UTC+08:00) Hong Kong Standard Time (UTC+08:00) Irkutsk Standard Time (UTC+08:00) Malaysia Time (UTC+08:00) Malaysia Time (UTC+08:00) Philippine Standard Time (UTC+08:00) Singapore Standard Time (UTC+08:00) Taipei Standard Time (UTC+08:00) Ulaanbaatar Standard Time (UTC+08:00) Ulaanbaatar Standard Time (UTC+08:45) Australian Central Western Standard Time // 以下忽略
根据时区编号获取一个时区 TimeZoneInfo.FindSystemTimeZoneById()
我们可以通过 TimeZoneInfo.GetSystemTimeZones() 返回的时区列表的 Id 来获取一个时区,使用的就是
TimeZoneInfo 的静态方法 FindSystemTimeZoneById()。比如我们要获取上海这个时区 Asia/Shanghai  则可以如下
TimeZoneInfo.FindSystemTimeZoneById("Asia/Shanghai");
使用范例如下
using System;
namespace datetime
{
    class Program
    {
        static void Main(string[] args)
        {
            var tzi = TimeZoneInfo.FindSystemTimeZoneById("Asia/Shanghai");
            Console.WriteLine(tzi.DisplayName);
        }
    }
}
创建一个自定义的时区 TimeZoneInfo.CreateCustomTimeZone()
我们还可以使用静态方法 TimeZoneInfo.CreateCustomTimeZone() 创建一个自定义的时区
TimeZoneInfo.CreateCustomTimeZone( "zh", // 编号 TimeSpan.FromHours(8), // 时间偏移 "中国时区", // 显示名称 "China time zone" // 可读性名称 );
使用范例如下
using System; namespace datetime { class Program { static void Main(string[] args) { var cnTimeZoneInfo = TimeZoneInfo.CreateCustomTimeZone("zh", TimeSpan.FromHours(8), "中国时区", "China time zone"); Console.WriteLine(cnTimeZoneInfo.DisplayName); } } }
跟时区相关的时间处理 DateTimeOffset.Parse() 和 DateTimeOffset.ToOffset()
我们可以通过静态方法 DateTimeOffset.Parse() 或者实例方法 [DateTimeOffset].ToOffset() 将日期时间从一个时区切换到另一个时区
using System; namespace datetime { class Program { static void Main(string[] args) { // 获取 UTC 时间 var dtu = DateTime.UtcNow; Console.WriteLine(dtu); // 获取 Asia/Shanghai 时区 var tzi = TimeZoneInfo.FindSystemTimeZoneById("Asia/Shanghai"); Console.WriteLine(tzi); var tzo = new DateTimeOffset(dtu); Console.WriteLine(tzo.ToOffset(tzi.BaseUtcOffset).DateTime); } } }
输出结果如下
10/27/2021 9:18:08 AM (UTC+08:00) China Standard Time 10/27/2021 5:18:08 PM
这里不得不说下 DateTimeOffset 类的构造函数,它有好多个构造函数,最值得注意的就2个,DateTimeOffset(DateTime) 和 DateTimeOffset(DateTime,TimeSpan),前者默认使用的是 UTC 时区,后者则需要传递 tzi.BaseUtcOffset 这个参数,也就是时区的时间偏移函数。
ASP.NET Core 设置默认时区 TZ 环境变量
好了,说回今天的重点,我们学习这么多,最主要的就是要知道 ASP.NET Core 如何设置默认的时区。
说起来有点悲哀,只有一种方法
使用 TZ 环境变量 
Unix 类系统,比如 Ubuntu、CentOS、MacOS
export TZ=Asia/Shanghai
Windows 系统,点击 开始 -> 设置 -> 时间与语言 -> 日期与时间