在DateTime的构造方法里,有个DateTimeKind类型的参数,在了解不同参数的区别后,可能会有一些新的理解。
DateTimeKind有3个枚举值,
1 | public enum DateTimeKind |
一、指定不同Kind的区别
1. 时间戳
在使用DateTime做加减法时,会忽略后面的Kind参数,只计算前面时间戳的值,举个例子,
1 | var local = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local); |
不同时区的0点,如果都转换成UTC时间的0点,时间戳的值是不同的,但是不转换的前提下,直接做加减法,它们之间的差值均为0,说明忽略了后面的Kind参数。
2. 表现形式
表现形式会受到DateTimeKind的值的影响,同样举个例子,
1 | var local = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local); |
local是本地机器的时区,我这里是东八区,比0时区快8个小时,所以东八区的1号0点,对应0时区的前一天下午4点。utc则即为0时区时间,unspecified使用的时区是本地机器时区,所以和local的是一样的。
3. 关于R格式的时间
1 | var local = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local); |
看到输出末尾的GMT,便知道这是格林威治时间,也就是0时区的时间。指定了不同Kind时区的时间,输出的时间却都是一样的,就像是后面的Kind参数没起作用一样。看到这些,感觉之前得出的结论被推翻,直到在官方文档上看到这么一句话,总算是打消了疑惑,
1 | 尽管 RFC 1123 标准将时间表示为协调世界时 (UTC),格式设置操作也不会修改正在格式化的 [DateTime]对象的值。 |
文档地址
意思就是,R格式是会忽略后面的Kind的值,只是将前半部分的时间进行格式化。
二、转换
1. Local和Utc
这两种类型的DateTime可以互相转换,
1 | var local = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local); |
local调用ToLocalTime方法时,没有变化,utc同理
2. Unspecified类型
此类型没有指定时区,当调用ToUnivesalTime方法时,它的时区是Local;当调用ToLocalTime方法时,它的类型是Utc。
三、两个时间戳
DateTime有两个时间戳,一个是DateTime.Now,一个是DateTime.UtcNow,这两个的区别就是前面的时间不同,后面的Kind也不同,具体要看时区,比如东八区下午4点来说,
1 | var utc = DateTime.UtcNow; |
当计算时间戳的时候,最好统一转换成UTC时间,然后再做加减法,
1 | var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); |