根据输入字符串中提供的时区解析日期时间

Parse Date time with respect to time zone provided in input string

我试图理解使用时区信息解析 utc 时间,但我的代码给出了奇怪的结果,或者至少我不理解。

var utcTime = DateTime.Parse("2019-05-20T13:00:00Z", null, System.Globalization.DateTimeStyles.RoundtripKind);
// utcTime = {5/20/2019 1:00:00 PM} (its kind is Utc and this is accepted)

var zonedTime1 = DateTime.Parse("2019-05-20T13:00:00-04:00", null, System.Globalization.DateTimeStyles.RoundtripKind);
//zonedTime1 = {5/20/2019 1:00:00 PM} (its kind is Local, but I was expecting {5/20/2019 9:00:00 AM} with Local kind)

var zonedTime2 = DateTime.Parse("2019-05-20T13:00:00+04:00", null, System.Globalization.DateTimeStyles.RoundtripKind);
//zonedTime2 = {5/20/2019 5:00:00 AM} (its kind is Local, but I was expecting {5/20/2019 5:00:00 PM} with Local kind)

我想知道我哪里错了或者我的期望哪里错了。如果 utcTime 被正确解析,那么为什么 zonedTime1 和 zonedTime2 不正确?

ISO 8601 时间戳中的偏移量描述了在本地时间部分已经 调整过的 UTC 偏移量。因此:

  • 2019-05-20T13:00:00-04:00 = 2019-05-20T17:00:00Z = 2019-05-20T13:00:00-04:00
  • 2019-05-20T13:00:00+04:00 = 2019-05-20T09:00:00Z = 2019-05-20T05:00:00-04:00

根据您的预期结果,我相信您希望 13:00:00 在所有三种情况下都成为 UTC 值,但事实并非如此。

其他几件事:

  • 文化通过 null 与通过 CultureInfo.CurrentCulture 相同。您最好为 ISO 8601 时间戳传递 CultureInfo.InvariantCulture,因为当当前文化使用 non-Gregorian 日历系统时,它既可以提高性能又可以防止错误。

  • 解析为DateTime时,如果输入字符串中存在any偏移量,则结果将调整为本地时区。转换时会考虑原始偏移量,但不会保留。因此,在许多情况下,您最好使用 DateTimeOffset 类型。