使用正确的时区和种类解析日期时间c#

时间:2016-01-20 22:32:40

标签: c# parsing datetime datetimeoffset

我在数据库中有一个日期时间,我使用SqlDataReader读取它,然后将其强制转换为(DateTime)。在投射后,其Kind属性为DateTimeKind.Unspecified

然后我有另一个字符串,我从其他来源读取。它的格式类似于2016-01-20T22:20:29.055Z。我做DateTime.Parse("2016-01-20T22:20:29.055Z"),它的Kind属性是DateTimeKind.Local。

如何正确解析两个日期时间以进行比较?我需要使用DateTimeOffsets吗?我该如何解析它们?

由于

4 个答案:

答案 0 :(得分:4)

因为SQLReader无法合理地推断出DateTimeKind,所以它将其保留为未指定。您将要使用DateTime.SpecifyKind将输出上的DateTimeKind从SQLReader更改为适当的值。如果您只处理UTC和一个一致的本地时区,这可以正常工作;否则,你真的应该在你的代码和SQL数据库中使用DateTimeOffset。

字符串" 2016-01-20T22:20:29.055Z"符合ISO 8601并且是UTC日期;但是,只有1个参数的DateTime.Parse最终可以执行到本地时间的转换。根据文件:

  

通常,Parse方法返回一个Date类型的对象   属性是DateTimeKind.Unspecified。但是,Parse方法可以   还执行时区转换并设置Kind的值   属性不同,取决于s和样式的值   参数:

  • 如果s包含时区信息,则转换日期和时间 到当地时区的时间,种类是DateTimeKind.Local。
  • 如果s包含时区信息,则样式包含 AdjustToUniversalflag,日期和时间转换为Coordinated 世界时(UTC)和种类是DateTimeKind.Utc。
  • 如果s包含Z或GMT时区指示符,则样式包括 RoundtripKind标志,日期和时间被解释为UTC和 种类是DateTimeKind.Utc。

另请参阅Derek Fowler博客中的UTC gotchas in .NET and SQL Server,了解有关该主题的更多信息。

答案 1 :(得分:2)

在您的第二个示例中,2016-01-20T22:20:29.055Z提供了时区信息; ' Z'最后表示时间戳用于协调世界时(UTC)。但是,DateTime.Parse()将使用DateTimeKind.Local默认其转化,除非指定了特定时区。您可以使用DateTime.ParseExact更具体。

至于为什么数据库中的日期时间值是Unspecified,这可能是因为它们根本不包含时区指示。检查您的数据库值是否指定了时区信息,方法是使用' Z'最后或指定一个确切的时区,例如2016-01-20T22:20:29.055-07:00(UTC-7)。

答案 2 :(得分:0)

您可以使用以下内容:

string format = "ddd dd MMM h:mm tt yyyy";
DateTime dateTime = DateTime.ParseExact(dateString, format,
    CultureInfo.InvariantCulture);

在格式变量中,您可以放置​​所需的格式,并将其传递给ParseExact函数。

希望它有所帮助。

答案 3 :(得分:0)

您缺少数据库中的日期时间上下文(偏移量)。您应该在datetimeoffset列或datetime列中保留它,但是保持utc日期时间。 并且总是比较两个utc日期时间。