我有两个DateTime
变量。每个都有一个存储在变量中的时区,因此当我使用包括zzz的格式ToString
时,我会得到一个包括+01:00
的字符串。
在设计时,我不知道时区是什么,我希望变量之间的时区不同。
我想比较两个DateTime
值,这样我就知道哪一个是最近的。
例如,如果变量A是2015-07-04T02:00:00+03:00
,变量B是2015-07-03T18:00:00-07:00
,则B>A。
我用C#写什么来告诉我这一点?(我宁愿不使用第三方库。(
(致SO问题关闭狂热者:我已经花了几个小时使用谷歌、MSDN和SO对此进行了调查,我很困惑。我在SO上找不到与此非常相似的问题。我相信这个问题的答案会帮助其他人。(
你说:
我有两个DateTime变量。每个都有一个存储在变量中的时区,所以当我使用包括zzz在内的格式ToString时,我会得到一个包括+01:00的字符串。
这是一个常见的误解。DateTime
在变量中没有存储时区。它只有一个Kind
属性,属于DateTimeKind
类型,可以是Utc
、Local
或Unspecified
。
调用ToString
时,zzz
格式说明符使用Kind
属性来确定要显示的偏移量。
-
当
Kind
是DateTimeKind.Utc
时,偏移量总是+00:00
。 -
当
Kind
是DateTimeKind.Local
时,偏移量是从执行代码的计算机上的本地时区确定的。例如,我的计算机设置为美国太平洋时间,因此偏移量将为-08:00
或-07:00
,具体取决于夏令时是否有效。 -
当
Kind
是DateTimeKind.Unspecified
时,行为与它是Local
时相同。请记住,其他方法以不同的方式处理Unspecified
——这只是zzz
说明符的特定行为。
MSDN实际上说:
因此,不建议将"zzz"格式说明符与
DateTime
值一起使用。
回到你的问题:
在设计时,我不知道时区是什么,我希望变量之间的时区不同。
则不能使用DateTime
。您应该使用DateTimeOffset
,因为它保留了特定的时区偏移,而不是使用DateTimeKind
。
例如,如果变量A是2015-07-04T02:0:00+03:00,变量B是2015-07-03T18:00:00-07:00,那么B>A。我在C#中写什么来告诉我这一点?
DateTimeOffset a = DateTimeOffset.Parse("2015-07-04T02:00:00+03:00");
DateTimeOffset b = DateTimeOffset.Parse("2015-07-03T18:00:00-07:00");
bool result = b > a; // true
另请参阅:DateTime与DatetimeOffset
此外
正如古斯塔夫所指出的,只要在比较之前转换回世界时,就可以只使用DateTime
。这是由于DateTime
隐藏的第四种状态(更多信息请点击此处(。该状态在解析过程中设置正确,并且在调用ToUniversalTime
时会被考虑在内。则比较具有可操作的有效UTC时间。
DateTime A = DateTime.Parse("2015-11-01T01:00:00-07:00");
DateTime B = DateTime.Parse("2015-11-01T01:00:00-08:00");
Console.WriteLine(A.ToUniversalTime().ToString("'A: 'yyyy'-'MM'-'dd hh:mm:ss"));
Console.WriteLine(B.ToUniversalTime().ToString("'B: 'yyyy'-'MM'-'dd hh:mm:ss"));
Console.WriteLine( B.ToUniversalTime() > A.ToUniversalTime() );
Console.WriteLine( B > A );
结果:
A: 2015-11-01 08:00:00
B: 2015-11-01 09:00:00
True
False
如果您的本地时区设置为太平洋时间,您将得到上述结果。然而,如果设置为其他值,则可能会得到最后一个结果的True
,因为这些值可能已被解析到您所在时区的不同本地时间,即使它们是太平洋时区的相同本地时间。
使用DateTimeOffset
仍然更简单,转换更少,并且不受本地时区的影响。
你试过这个吗?
var A = DateTime.Parse("2015-07-04T02:00:00+03:00");
var B = DateTime.Parse("2015-07-03T18:00:00-07:00");
Console.WriteLine( B > A );