【问题标题】:Parsing Date Time String returns Incorrectly解析日期时间字符串返回不正确
【发布时间】:2015-12-19 11:52:38
【问题描述】:

我有一个 azure Web 服务,可以将 XML 文件传送给许多客户。

用户将一个 XML 文件发送到 Web 服务,它会将 XML 反序列化为 Object,然后将其序列化为客户所需的 XML 格式。

我遇到了一个奇怪的情况,发送到 Web 服务的 XML 文件中有两种不同的 DateTime 格式,在这种情况下,输出的 XML 文件中的 DateTimes 是不正确的。但是,如果我在两个单独的文件中提供两个 DateTimes,则两者都被正确解析。

这是两个日期时间:

日期="2015-09-23T14:30:00+01:00"

日期="2015-09-23T14:30:00"

当在一个文件中解析时,它们都解析为 14:30,这是正确的,但是当两种格式都在文件中时,第二个 DateTime 解析为 15:30 和第一个 14:30。

我已尝试分配 CultureInfo,设置为当地时间。

我正在使用XmlSerializer ClassXmlSerializer.Deserialize Method 将发送到Web 服务的XML 文件读取到我创建的对象中。

然后我有一个简单的映射器,它将值写入 XML 并更改一些属性和节点名称。将 DateTime 写入字符串的代码是:

xmlWriter.WriteAttributeString("startdatetime", dateTime.ToString("s"))

真正让我震惊的是,当它们位于单独的文件中时,这一切都有效,但当它位于具有两种单独的 DateTime 格式的文件中时,这一切都有效。

【问题讨论】:

  • 您确实应该在您的解决方案中使用通用的 UTC 时间格式吗?
  • 是的,我应该这样做,但我的经理目前不会同意这样做。
  • 当您将属性从 DateTime 更改为 DateTimeOffset 时会发生什么?
  • 如果你把它解析为DateTimeOffset,然后像这样序列化它:dto.DateTime.ToString("s") - 你应该得到正确的结果。
  • 预期输出是什么?

标签: c# xml datetime


【解决方案1】:

有几件事对你不利:

  1. 您的意见多种多样。

    • "2015-09-23T14:30:00+01:00" 是明确的特定时刻,由日期、时间和与 UTC 的偏移量描述。

    • "2015-09-23T14:30:00" 不提供偏移量,因此它不会直接映射到特定时间点。

  2. "2015-09-23T14:30:00+01:00"XmlSerializer 反序列化为DateTime 时,偏移量被应用到UTC,然后它被转换为它所在服务器的本地时区在跑。结果有DateTimeKind.Local

    • 在云中,本地时区已经是 UTC,因此它减去一个小时并停留在那里,尽管它仍然是 DateTimeKind.Local,而不是 DateTimeKind.Utc

    • 还请注意您声明了15:30,但14:30+01:0013:30 UTC。此外,当只有一个或另一个在单个文件中时,我看不出行为有任何差异。如果可以,请编辑您的问题以显示以这种方式重现问题的代码。

  3. "2015-09-23T14:30:00"XmlSerializer 反序列化为DateTime 时,它将具有DateTimeKind.Unspecified。如果您打算用它来表示 UTC,那是您事后应用的假设。它也可能是其他时区的当地时间。要明确表示为 UTC,原始字符串应该是 "2015-09-23T14:30:00Z""2015-09-23T14:30:00+00:00"

  4. "2015-09-23T14:30:00+01:00"XmlSerializer 反序列化为DateTimeOffset 时,它会阻塞。 XmlSerializer 类仍然不理解 DateTimeOffset 的标准 ISO 格式。有some workarounds here,但实际上这应该在框架中修复(恕我直言)。

那该怎么办?好吧,最简单的事情(也是大多数人最终会做的事情)是从这些类中删除 DateTime 属性并使用 string 代替。这样您就可以获得数据中提供的确切值。然后,您可以自己通过DateTime.ParseDateTimeOffset.Parse 使用这些方法提供的所有各种选项。有一个通过“伙伴属性”方法执行此操作的示例in this answer here

将两个字符串值转换为DateTimeOffset 后,您可以使用.DateTime 属性获取原始提供的原始日期和时间,或者使用.UtcDateTime 属性或任何其他属性。

请注意,如果您将没有偏移量的 ISO 字符串解析为 DateTimeOffset,则会为您应用一个。默认情况下,它将使用运行它的计算机的本地时区。如果您的代码在 Azure 中,那将是 UTC,或 +00:00 - 所以应该没问题。

【讨论】:

  • 谢谢。关于解析同一文件中的 DateTimes,这就是让我感到困惑的地方,当我解析具有 UTC 偏移量的文件时,它会正确解析,当我解析没有偏移量的文件时,它会正确解析,然后当两者都在同一个文件中时文件 UTC 偏移时间解析正确,但没有偏移的 DateTime 将提前一小时解析。我看不出会导致这种情况发生的代码有什么不同。
  • 能否更新您的问题以包含MCVE?谢谢。 (虽然解决方案可能是相同的 - 使用字符串)。
猜你喜欢
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-28
  • 1970-01-01
相关资源
最近更新 更多