我正在尝试使用.NET的DateTime结构解析ISO8601格式的日期/时间字符串。

为了让我对问题有一个全面的了解,我将使用.NET和JavaScript进行测试。我目前在英国(英国夏令时,UTC + 01:00)。

我对ISO8601的理解是:


当字符串后缀“ Z”时,时间以UTC表示。
当字符串以“ +/- hh:mm”为后缀时,时间表示为
当地时间,其中“ +/- hh:mm”表示与UTC的偏移量。


请考虑以下ISO8601日期/时间格式字符串:

"1987-01-05T08:45:30.500+0100"


鉴于以上几点,此字符串表示本地时间为“ 08:45:30”,UTC时间为“ 07:45:30”

当前的时区测试(.NET)

DateTime now = DateTime.Now;
Console.WriteLine(now.ToLocalTime()); // 27/08/2013 12:02:43
Console.WriteLine(now.ToUniversalTime()); // 27/08/2013 11:02:43


当前的时区测试(JavaScript)

var now = new Date(Date.now());
now.toString(); // Tue Aug 27 2013 12:03:46 GMT+0100 (GMT Daylight Time)
now.toUTCString(); // Tue, 27 Aug 2013 11:03:46 GMT


除了两个示例之间的微小差异(分钟/秒)之外,它们还完全返回了我对英国夏令时(UTC + 01:00)的期望。分钟/秒的差异是因为我无法同时运行.NET测试和JavaScript测试。

现在,让我们使用我的ISO8601日期/时间格式的字符串:

解析ISO8601格式字符串(.NET)

DateTime dt = DateTime.Parse("1987-01-05T08:45:30.500+0100");
Console.WriteLine(dt.ToLocalTime()); // 05/01/1987 07:45:30
Console.WriteLine(dt.ToUniversalTime()); // 05/01/1987 07:45:30


解析ISO8601格式字符串(JavaScript)

var dt = new Date("1987-01-05T08:45:30.500+0100");
dt.toString(); // Mon Jan 05 1987 07:45:30 GMT+0000 (GMT Standard Time)
dt.toUTCString(); //Mon, 05 Jan 1987 07:45:30 GMT


这似乎与显示日期/时间“现在”的示例不一致。当“现在”的示例在英国夏令时(UTC + 01:00)中显示时,为什么显示为好像我在英国冬令时(UTC + 00:00)一样?

如果我更改了时区设置,则可以获得本地/通用时间的预期结果,但是如果将它们设置为我的当前时间/时区,则结果似乎不一致。

编辑:简而言之,当我尝试解析字符串时,好像.NET和JavaScript都在忽略夏令时/英国夏令时(UTC + 01:00)。结果对于冬天是正确的,并且当我实际更改时间/区域时也可以正确...但是按现状,这在我在英国测试过的“任何”机器上都是不正确的。

最佳答案

英国在夏季(8月27日,示例中为“现在”)使用夏季时间(将时钟提前一小时),但在冬季(1月5日,根据您对“ 1987-01-05T08:45”的解析)使用夏季时间: 30.500 + 0100“)。

实际上,在冬天,英国使用UTC。您的计算机似乎带有英式TimeZoneInfo。您可以使用TimeZoneInfo.Local.DisplayName(自.NET 3.5开始)或TimeZone.CurrentTimeZone.StandardName(旧)进行检查。

您可以使用dt.IsDaylightSavingTime()进行检查。

加成:

我的答案仅关于.NET(但对JavaScript可能也适用吗?)。您提供的示例完全按预期工作。 1987年1月的日期和时间将转换为您当地的区域,该区域应该是英国,而1987年1月,由于冬季,英国的时间是+0000。您给定的时间字符串带有+0100标记(就好像它是从德国或其他国家到英国东部一小时),并且在解析该字符串时会得到确认。由于1987年夏天英国(和所有EEC)观察到夏令时(夏令时),所以1987年夏的日期将正确地进行了不同的转换。

总结:在解释时间时,考虑偏移量指示符或区域说明符+0100。这将在您的计算机上转换为英国时间。如果要转换为UTC而不是转换为计算机的本地时间,请使用带有DateTimeStyles枚举并包含标志DateTimeStyles.AdjustToUniversal的重载。

如果想要一个更好地表示时间和绝对区域的值,请考虑使用结构DateTimeOffset而不是DateTime。您也可以考虑NODA时间而不是.NET类型。

09-30 18:03
查看更多