C#和JavaScript之间Timespan差异的解释

时间:2014-02-28 13:31:26

标签: c# javascript datetime

这基于Computing milliseconds since 1970 in C# yields different date than JavaScriptC# version of Javascript Date.getTime()

对于所有这些计算,假设它们是在中央标准时间内完成的,因此比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以来的毫秒数。这一切都很好。在链接的问题中,人们要求将此功能转换为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

我还没有找到解释为什么我们将代表Unix Epoch的DateTime留给DateTimeKind Unspecified以便能够匹配JavaScript。我们不应该使用DateTimeKind.Utc获得正确的结果吗?我不明白什么细节?对我来说,这是一个纯粹的学术问题,我只是好奇为什么会这样运作。

2 个答案:

答案 0 :(得分:6)

正如您正确指出的那样,.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);
  1. e - s不正确,因为s不是UTC时间。
  2. e.ToUniversalTime() - s.ToUniversalTime()不正确,因为e不再包含与UTC的偏移量(就像JavaScript中的计算一样)
  3. e.ToUniversalTime() - s 正确,因为我们正在使用UTC时间我们减去的时间包括与UTC的偏移量。
  4. 当我直接处理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为单位的,而我们处理的时间仍有其原始偏移量。

答案 1 :(得分:2)

  

据我所知,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