【问题标题】:Difference between JS and .NET daylight saving behaviorJS 和 .NET 夏令时行为的区别
【发布时间】:2019-12-27 13:57:13
【问题描述】:

我试图让 C# 和 JS 在 JS Date 和 .NET DateTime 对象上添加分钟时生成相同的结果。 我的系统使用的是希腊文化设置,但很可能您会在您的机器上得到类似的结果(如果您使用这些值)。 我有这个使用 moment.js 的 JS 代码:

var dt1 = new Date(2020, 0, 19, 0, 0, 0);
var m1 = moment(dt1);
[m1.toString(), m1.add(100980, 'minutes').toString()]

>  ["Sun Jan 19 2020 00:00:00 GMT+0200", "Sun Mar 29 2020 04:00:00 GMT+0300"]

..还有 LinqPad 中的这个 C# 代码:

var ci = CultureInfo.CreateSpecificCulture("el-GR"); //CultureInfo.InvariantCulture; //CultureInfo.CurrentCulture;
var dt = new DateTime(2020, 1, 19, 0, 0, 0, 0, ci.Calendar, DateTimeKind.Local);
dt.ToString("G", ci).Dump();
var dt2 = dt.AddMinutes(100980);
dt2.ToString("G", ci).Dump();

> 19/1/2020 12:00:00 πμ
> 29/3/2020 3:00:00 πμ

...当使用不变的文化打印时:

var ci = CultureInfo.CreateSpecificCulture("el-GR"); //CultureInfo.InvariantCulture; //CultureInfo.CurrentCulture;
var dt = new DateTime(2020, 1, 19, 0, 0, 0, 0, ci.Calendar, DateTimeKind.Local);
dt.ToString("G", CultureInfo.InvariantCulture).Dump();
var dt2 = dt.AddMinutes(100980);
dt2.ToString("G", CultureInfo.InvariantCulture).Dump();

> 01/19/2020 00:00:00
> 03/29/2020 03:00:00

谁能告诉我为什么我得到不同的结果? 系统设置是一样的,我尝试使用CurrentCultureCreateSpecificCulture("el-GR") 都没有得到与JS结果相似的地方。

我什至在 JS 中创建了自己的 addMinutes(),但我仍然遇到同样的问题。

似乎 JS 在开始日期后的 100980 分钟进行了夏令时切换(如果添加 100979 分钟,您会看到),但 C# 没有!根据Wikipedia,JS 行为是正确的行为。但到目前为止,我很确定 .NET 也是正确的。根据我所做的快速测试,C# 似乎在 70.2 天前进行了切换。

在向日期添加分钟时,我必须做些什么才能在两种语言之间获得相同的结果?

更新:

我试过NodaTime,好像和JavaScript一致:

var dt0 = new DateTime(2020, 1, 19, 0, 0, 0, 0, ci.Calendar, DateTimeKind.Local).AcServerToUtc();
Duration duration = Duration.FromMinutes(100980);
Instant start = Instant.FromDateTimeUtc(dt0.AcMakeKindUtc());
Instant future = start + duration; // Or now.Plus(duration)
var zone =  DateTimeZoneProviders.Tzdb.GetSystemDefault();
future.InZone(zone).LocalDateTime.ToString("G", CultureInfo.InvariantCulture).Dump();

> 03/29/2020 04:00:00

所以,这似乎是一个可能的解决方案!

【问题讨论】:

  • 试试noda time - 如果有更好的时区支持然后CLR
  • @stuartd 感谢您的建议。我过去听说过nodatime。但是,我们的代码库正在使用 .NET Framework 的功能,并且很难切换,但我一定会尝试一下,看看是否有任何变化。奇怪的是,我们从来没有注意到 C# 时区/夏令时有什么问题,所以我对 C# 的功能有问题的想法有点怀疑。我将更新问题以分享我的结果。
  • @stuartd 是的! NodaTime 似乎同意 JavaScript,因此切换到它可能是一个很好的解决方案。谢谢!如果您愿意,请发布答案,以便我接受。或者,如果你愿意,我可以自己写一个答案。
  • 您应该发布更新作为答案并接受它。但是,它并没有真正回答为什么会出现差异或如何在不使用 3rd 方库的情况下在 .NET 中修复它的问题。

标签: javascript c# .net date dst


【解决方案1】:

问题是AddMinutes 调用是在DateTimeDateTimeKind.Local 上完成的。尽管被标记为这种类型,DateTime 对象上的 math 并未考虑时区。 即使是当地时间

由于您使用的是本地类型,因此您可以简单地转换为 UTC,进行数学运算,然后再转换回来。

var dt2 = dt.ToUniversalTime().AddMinutes(100980).ToLocalTime();

您可能还想考虑改用DateTimeOffset 类型,并使用TimeZoneInfo.ConvertTime 执行时区转换。

【讨论】:

  • 这看起来很有趣。可能是使用NodaTime 的替代方法。谢谢。 :)
【解决方案2】:

我最终使用了NodaTime,正如我在上面的问题更新中所写的那样。

它始终不同意moment.js,但我觉得它更经常同意它。

我猜夏令时是一大堆乱七八糟的事情,没有人能处理得足够好。

【讨论】:

    猜你喜欢
    • 2013-10-13
    • 2015-11-14
    • 2012-03-21
    • 2015-08-11
    • 1970-01-01
    • 1970-01-01
    • 2014-04-18
    • 2012-10-31
    • 2012-03-25
    相关资源
    最近更新 更多