C#和JavaScript之间Timespan差异的解释
这基于自1970年以来的计算毫秒数,C#产生的日期不同于 Javascript Date.getTime()的 JavaScript和C#版本 。
对于所有这些计算,假设它们在中央标准时间内完成,因此比UTC低6小时(此偏移将在稍后再次出现)。
据我所知,JavaScript Date
对象基于Unix Epoch(1970年1月1日午夜)。 所以,如果我这样做:
//remember that JS months are 0-indexed, so February == 1 var d = new Date(2014,1,28); d.getTime();
我的输出将是:
1393567200000
这表示自Unix Epoch以来的毫秒数。 这一切都很好。 在链接的问题中,人们要求将此function转换为C#,而“天真”的实现通常看起来像这样:
//the date of interest in UTC DateTime e = new DateTime(2014, 2, 28, 0, 0, 0, DateTimeKind.Utc); //the Unix Epoch DateTime s = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); //the difference between the two TimeSpan t = (e - s); var x = t.TotalMilliseconds; Console.WriteLine(x);
哪个产生输出:
1393545600000
这是21,600,000毫秒或6小时的差异:与完成这些计算的时区的UTC的精确偏差。
为了使C#实现与JavaScript匹配,这是实现:
//DateTimeKind.Unspecified DateTime st=new DateTime(1970,1,1); //DateTimeKind.Unspecified DateTime e = new DateTime(2014,2,28); //translate e to UTC, but leave st as is TimeSpan t= (e.ToUniversalTime()-st); var x = t.TotalMilliseconds; Console.WriteLine(x);
这将给我输出匹配JavaScript输出:
1393567200000
我还没有找到解释为什么我们将DateTime
代表Unix Epoch并使用DateTimeKind
Unspecified
以便能够匹配JavaScript。 我们不应该使用DateTimeKind.Utc
获得正确的结果吗? 我不明白什么细节? 这对我来说是一个纯粹的学术问题,我只是好奇为什么这样做。
正如您正确指出的那样, .getTime()
返回“自1970年1月1日00:00:00 UTC以来的毫秒数”。
这意味着.getTime
(正如您所注意到的)包括计算中与UTC的偏移量。
为了使C#代码反映这一点,您从中减去的时间必须包括时区信息,而1970年1月1日00:00:00 必须是UTC时间。
通过一些示例可能更容易理解。 鉴于:
DateTime e = new DateTime(2014, 2, 28, 0, 0, 0); DateTime s = new DateTime(1970, 1, 1, 0, 0, 0);
-
e - s
不正确,因为s
不是UTC时间。 -
e.ToUniversalTime() - s.ToUniversalTime()
不正确,因为e
不再包含UTC的偏移量(就像JavaScript中的计算一样) -
e.ToUniversalTime() - s
是正确的,因为我们正在使用UTC时间,而我们减去的时间包括UTC的偏移量。
当我直接处理DateTime.Ticks
时,这对我来说更容易看到:
e.Ticks // 635291424000000000 s.Ticks // 621355968000000000 e.Ticks - s.Ticks // 13935456000000000 ("naive" implementation) e.ToUniversalTime().Ticks - s.Ticks // 13935636000000000 (correct output)
同样,最后一个例子符合我们的所有要求。 Unix纪元是UTC,而我们处理的时间仍有其原始偏移量。
据我所知,JavaScript Date对象基于Unix Epoch(1970年1月1日午夜)。
对,他们是。 在内部,距离纪元只有几毫秒。 但是当你调用日期构造函数或查看.toString()
的输出时,它正在使用代码运行的本地时间。
如果要以UTC格式指定输入,则必须使用不同的咒语:
var ts = Date.UTC(2014,1,28); // returns a numeric timestamp, not a Date object var dt = new Date(ts); // if you want a date object var s = dt.toUTCString(); // if you want the output to be in UTC