简体   繁体   English

.Net 和 Javascript 之间的日期差异

[英]Differences in dates between .Net and Javascript

I had an issue where dates were out by one day when displaying on an asp.net web form.我遇到了一个问题,当在 asp.net 网络表单上显示时,日期已经过了一天。 These dates are only used for display so I can pass them as strings to resolved the issue, but I'm curious about why I'm seeing this behaviour.这些日期仅用于显示,因此我可以将它们作为字符串传递以解决问题,但我很好奇为什么我会看到这种行为。

I'm in Ireland, and while Ireland is more or less in line with GMT, we use IST (Irish Standard Time) during summer instead of DST and then revert to GMT for Winter.我在爱尔兰,虽然爱尔兰或多或少与 GMT 一致,但我们在夏季使用 IST(爱尔兰标准时间)而不是 DST,然后在冬季恢复为 GMT。 This has the same effect as being on GMT, but "officially" is slightly different.这与在 GMT 上的效果相同,但“官方”略有不同。

As we're not on GMT, in the past, IST and DST didn't always line up.由于我们不在格林威治标准时间,过去,IST 和 DST 并不总是排队。

For example, in 1958, IST started in the 20th April and ended on the 5th October whereas, DST started on the 27th of April and ended on 26th of October.例如,在 1958 年,IST 从 4 月 20 日开始,到 10 月 5 日结束,而 DST 从 4 月 27 日开始,到 10 月 26 日结束。

So if a date between the 5th and 26th of October 1958 is passed to JS, JS will display it as the previous day.因此,如果将 1958 年 10 月 5 日至 26 日之间的日期传递给 JS,则 JS 会将其显示为前一天。

I wrote this this code to try and understand what's going on:我写了这段代码来尝试理解发生了什么:

        DateTime date = new DateTime(1958, 10, 4);

        while (date <= new DateTime(1958, 10, 30))
        {
            Console.WriteLine($"normal   : {date} | isDst? : {date.IsDaylightSavingTime()}");
            Console.WriteLine($"universal: {date.ToUniversalTime()} | isDst? : {date.ToUniversalTime().IsDaylightSavingTime()}");
            Console.WriteLine($"local    : {date.ToLocalTime()} | isDst? : {date.ToLocalTime().IsDaylightSavingTime()}");
            
            Console.WriteLine("-------------------------");
            date = date.AddDays(1);
        }                            

Which produced this output (truncated):产生了这个输出(截断):

一个

So I can see there are a number of days being mis identified as DST days, but it doesn't seem like that would cause this?所以我可以看到有很多天被错误地识别为 DST 天,但这似乎不会导致这种情况? If both .Net and JS though they were DST days, then surely the end result should be correct?如果 .Net 和 JS 虽然都是夏令时,那么最终结果肯定是正确的吗?

Additionally, why is there a 2 hour difference between the output of ToUniversalTime and ToLocalTime during DST?另外,为什么在 DST 期间 ToUniversalTime 和 ToLocalTime 的输出之间有 2 小时的差异?

Here's a screenshot of JS processing a few dates duirng this problematic window这是 JS 在这个有问题的窗口中处理几个日期的屏幕截图

在此处输入图像描述

You can see that JS (or chrome?) is aware that during the 5th to the 27th of that year, Ireland is no longer on GMT+1 (even though it still says it's IST) so why is the date passed from VB an incorrect date?您可以看到 JS(或 chrome?)知道在当年的 5 日到 27 日期间,爱尔兰不再是 GMT+1(即使它仍然说它是 IST),那么为什么从 VB 传递的日期不正确日期? I though they both got their datetime information from the same source ie the host pc?我虽然他们都从同一个来源(即主机电脑)获得了他们的日期时间信息?

You appear to be running .NET on Windows, in which case .NET is using the Windows time zone data for your local time zone.您似乎在 Windows 上运行 .NET,在这种情况下,.NET 将 Windows 时区数据用于您的本地时区。

The Windows time zone data does not have the full history of time zone changes from all time. Windows 时区数据没有完整的时区更改历史记录。 Microsoft's policy only guarantees historical data is present for dates from 2010 forward, though some time zones have historical data before then. Microsoft 的政策仅保证存在 2010 年以后的历史数据,尽管某些时区在此之前有历史数据。

Conversely, Chrome is using time zone data from ICU , which uses IANA time zone data .相反,Chrome 使用来自ICU的时区数据,它使用IANA 时区数据 IANA time zones have historical data since at least 1970, though many time zones have historical data before then. IANA 时区至少从 1970 年开始就有历史数据,尽管许多时区在此之前都有历史数据。

With specific regard to Ireland, IANA has Irish time zone data going back to 1880. Windows has no history for Ireland at all, so it assumes the current rule has always been in effect.具体到爱尔兰,IANA 的爱尔兰时区数据可以追溯到 1880 年。Windows 根本没有爱尔兰的历史记录,因此它假定当前规则一直有效。 In reality, the current rule has been in effect since Oct 1968, so any dates before then will only have accurate time zone information in the IANA data.实际上,当前规则自 1968 年 10 月起生效,因此在此之前的任何日期都只会在 IANA 数据中包含准确的时区信息。

If you run the same .NET code you showed above on Linux or MacOS, you'll see that .NET will use IANA time zone data on those platforms and your results will match up for 1958. Or, if you pick a more recent date your results will match on Windows too.如果您在 Linux 或 MacOS 上运行上面显示的相同 .NET 代码,您会看到 .NET 将在这些平台上使用 IANA 时区数据,并且您的结果将与 1958 年匹配。或者,如果您选择更近的日期您的结果也将在 Windows 上匹配。

In short - don't run these sorts of tests on old dates and expect to get the same fidelity that you'll get with modern dates.简而言之 - 不要在旧日期上运行这些类型的测试,并期望获得与现代日期相同的保真度。

You also asked:你还问:

Additionally, why is there a 2 hour difference between the output of ToUniversalTime and ToLocalTime during DST?另外,为什么在 DST 期间ToUniversalTimeToLocalTime的输出之间有 2 小时的差异?

Your date variables are all DateTime where .Kind is DateTimeKind.Unspecified .您的date变量都是DateTime其中.KindDateTimeKind.Unspecified The IsDaylightSavingTime method will treat such values as if they belonged to the local time zone, as if they actually had DateTimeKind.Local . IsDaylightSavingTime方法会将这些值视为属于本地时区,就好像它们实际上具有DateTimeKind.Local一样。 The same is true for the ToUniversalTime method, however, the ToLocalTime method will assume that DateTime values with DateTimeKind.Unspecified kind are actually in terms of UTC - as if they were DateTimeKind.Utc . ToUniversalTime方法也是如此,但是, ToLocalTime方法将假定具有DateTimeKind.Unspecified种类的DateTime值实际上是按照 UTC 表示的 - 就好像它们是DateTimeKind.Utc一样。 Thus, when DST is in effect, date.ToUniversalTime() shifts an hour backward , and date.ToLocalTime() shifts an hour forward .因此,当 DST 生效时, date.ToUniversalTime()向后移动一个小时, date.ToLocalTime()向前移动一个小时。

You can avoid such ambiguities by using DateTimeOffset instead of DateTime .您可以通过使用DateTimeOffset而不是DateTime来避免这种歧义。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM