如何比较DateTime值,考虑到时区?
我有两个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:00: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
此外
正如Gustav指出的那样,只要在比较之前转换回通用时间, 就可以使用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 );