我正在将DateTime转换为Unix时间。据我了解,这两种方法应该返回相同的结果。
选项1
DateTime dtfoo = new DateTime(2010, 10, 20);
DateTimeOffset dtfoo2 = new DateTimeOffset(dtfoo).ToUniversalTime();
long afoo = dtfoo2.ToUnixTimeMilliseconds();
选项2
DateTime dtfoo = new DateTime(2010, 10, 20);
DateTimeOffset dtfoo2 = new DateTimeOffset(dtfoo).ToUniversalTime();
long afoo = (Int64)(dtfoo2.Subtract(new DateTime(1970, 1, 1))).TotalMilliseconds;
选项1返回1287525600000,选项2返回1287529200000。
为什么我得到不同的结果?
答案 0 :(得分:3)
通知:我现在使用的是UTC + 9,问题的根源是时区偏移量,因此请理解,我看到的Unix时间可能与您自己的时间有所不同。
区别在于您如何处理日期对象。根据由此产生的差异,我假设您的时区为CET(或者您使用的是rextester,我相信是在德国)。
考虑以下代码:
var dtfoo = new DateTime(2010, 10, 20);
var dtfoo2 = new DateTimeOffset(dtfoo);
var dtfoo3 = dtfoo2.ToUniversalTime();
DateTimeKind
of "Unspecified"创建一个DateTime
。DateTimeOffset
对象。由于未指定DateTimeKind,因此使用了UTC的系统时间偏移。为{2引用documentation:
如果DateTime.Kind的值为DateTimeKind.Local或DateTimeKind.Unspecified,则将新实例的DateTime属性设置为等于dateTime,并且将Offset属性设置为等于本地系统当前时区的偏移量。
现在让我们写出1-3的往返格式日期字符串:
2010-10-20T00:00:00.0000000
2010-10-20T00:00:00.0000000+09:00
2010-10-19T15:00:00.0000000+00:00
我使用的是UTC + 9,因此DateTimeOffset
的创建正确,偏移量为+ 9h。将其转换为通用后,我们将在19日下午3点到达。不幸的是,这导致.ToUnixTimeMilliseconds()
的输出为1287500400000
,即2010-10-19T15:00:00Z
。该值已取决于机器的时区。
因此,现在让我们看一下第二个示例:
DateTime dtfoo = new DateTime(2010, 10, 20);
DateTimeOffset dtfoo2 = new DateTimeOffset(dtfoo).ToUniversalTime();
long afoo = (Int64)(dtfoo2.Subtract(new DateTime(1970, 1, 1))).TotalMilliseconds;
好的,我们将其分为不同的部分,以便我们可以看到系统认为它们代表的时间(记住我在UTC + 9中):
new DateTime(2010, 10, 20).ToString("o")
-2010-10-20T00:00:00.0000000 new DateTimeOffset(dtfoo).ToString("o")
-2010-10-20T00:00:00.0000000 + 09:00 new DateTimeOffset(dtfoo).ToUniversalTime()
-2010-10-19T15:00:00.0000000 + 00:00 new DateTime(1970, 1, 1).ToString("o")
-1970-01-01T00:00:00.0000000 因此,您正在有效地执行此计算:
(DateTimeOffset.Parse("2010-10-19T15:00:00.0000000+00:00") - DateTime.Parse("1970-01-01T00:00:00.0000000")).TotalMilliseconds
这将输出1287532800000
,它等于2010-10-20T00:00:00Z。由于减法是如何完成的,因此您可以得到正确的结果:
DateTime
是implicitly cast到DateTimeOffset
,相当于new DateTimeOffset(DateTime.Parse("1970-01-01T00:00:00.000000"))
-这意味着两个输入日期都经过相同的时区更改。DateTime
的{{1}}属性,将subtraction的两个日期都转换为DateTimeOffset
对象。那么我们如何解决您的原始示例?通过构造.UtcDateTime
时指定偏移量,我们可以从方程式中取出本地时区偏移量:
DateTimeOffset
现在,这给了我们与上一个测试DateTime dtfoo = new DateTime(2010, 10, 20);
DateTimeOffset dtfoo2 = new DateTimeOffset(dtfoo, TimeSpan.Zero).ToUniversalTime();
long afoo = dtfoo2.ToUnixTimeMilliseconds();
中相同的值。如果通过使用1287532800000
简化此操作,则应确认我们走在正确的轨道上:
DateTimeOffset.Parse
我们可以看到它也输出Console.WriteLine(DateTimeOffset.Parse("2010-10-20T00:00:00Z").ToUnixTimeMilliseconds());
。
因此,总而言之,您的问题源于1287532800000
构造函数如何使用DateTimeKind DateTimeOffset(datetime)
或Unspecified
处理日期。根据您机器的时区,它会使您产生的通用时间产生偏差。这会导致不正确的Unix时间偏移。要解决该问题,只需按照我上面描述的方法之一创建您的Local
。
答案 1 :(得分:0)
差异可能是因为ToUnixTimeMilliseconds
不需要花费leap秒的时间。
文档内容如下:
Unix时间表示自此以来经过的秒数 1970-01-01T00:00:00Z(世界标准时间1970年1月1日,上午12:00)。它不是 考虑leap秒。此方法返回的数量 Unix时间中的毫秒数。
TimeSpan.TotalMilliseconds
并未提及。
此属性将该实例的值从刻度线转换为 毫秒。此数字可能包括整数和分数 毫秒。