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

Parse date time c# with correct timezone and kind

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

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

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

谢谢

你可以这样使用:

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

在格式变量中,你可以输入你想要的格式,并传递给ParseExact函数。

希望对您有所帮助。

在您的第二个示例中,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).

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

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

字符串“2016-01-20T22:20:29.055Z”是 ISO 8601 compliant and is a UTC date; however, DateTime.Parse 只有 1 个参数可以最终执行到本地时间的转换。根据文档:

Generally, the Parse method returns a DateTime object whose Kind property is DateTimeKind.Unspecified. However, the Parse method may also perform time zone conversion and set the value of the Kind property differently, depending on the values of the s and styles parameters:

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

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

我编写了一个快速的 C# 控制台应用程序并将其粘贴在下面。这会将 UTC 日期和时间转换为字符串(格式类似于另一个 post 中描述的 ISO 8601 格式,具有一些额外的精度),将其写入文件,从文件中读取(作为字符串)然后将其转换回 UTC 日期和时间。 然后它比较两个 UTC 日期时间对象,它们都是 UTC 类型,并且它们匹配。

<pre></p> <pre><code>class Program { // "2016-01-20T22:20:29.055Z" is ISO 8601 compliant and is a UTC date const string dtf = "yyyy-MM-ddTHH:mm:ss.fffffffZ"; static void Main(string[] args) { string file = @"c:\temp\file.txt"; DateTime dt = DateTime.UtcNow; using (var sw = new System.IO.StreamWriter(file)) { sw.WriteLine(dt.ToString(dtf, System.Globalization.CultureInfo.InvariantCulture)); } DateTime dtin; using (var sr = new System.IO.StreamReader(file)) { dtin = DateTime.ParseExact(sr.ReadLine(), dtf, System.Globalization.CultureInfo.InvariantCulture); } Console.WriteLine(dt.ToString(dtf) + "\r\n" + dtin.ToString(dtf) + "\r\nEquality:" + (dt == dtin)); Console.ReadLine(); } }