标准化DateTime.Now和DateTime.Utc

时间:2017-05-17 06:07:10

标签: c# datetime

我正在处理从服务器接收警报的应用程序。在处理警报时,我通过执行以下操作来计算上次发送警报的时间:

TimeSpan? alertDiffTimespan = DateTime.UtcNow - serverEventInfo.lastAlert

准确的时间跨度非常重要,因为它可以让我弄清楚服务器是否处于活动状态。

最近,我注意到有时serverEventInfo.lastAlert是正确的(即格式化为DateTime.UtcNow),有时则是当前时间提前/后一小时(即DateTime.Now)。我尝试过以下方法:

TimeSpan? alertDiffTimeSpan = DateTime.UtcNow - serverEventInfo.lastAlert.Value.ToUniversalTime()

但是这意味着所有设置为DateTime.UtcNow的值格式不正确,但设置为DateTime.Now的值是正确的。

我也尝试过确定DateTime.Kind,但是每次都标记为Unspecified,所以没有区别。

我可以做些什么来标准化我的应用程序中的传入DateTime值,这样无论是UtcNow还是Now值,我仍然可以正确处理它并获得正确的alertDiffTimeSpan

日期格式为{0:MM/dd/yyyy hh:mm:ss tt},并在服务器上设置如下String.Format("{0:MM/dd/yyyy hh:mm:ss tt}", DateTime.Now)String.Format("{0:MM/dd/yyyy hh:mm:ss tt}", DateTime.UtcNow)

1 个答案:

答案 0 :(得分:3)

如果您没有以某种方式指定时区信息,则无法猜测DateTime的正确值。听起来你的服务器可能会在本地(可能是多个时区)和UTC之间“随机”选择,你无法知道哪一个是哪个。

修正:

  • 对齐所有服务器以返回UTC时间并继续使用未指定时区的格式。读取服务器值时,请在结尾处指定Utc:DateTime.SpecifyKind(parsedDateTime, DateTimeKind.Utc)
  • 需要序列化数据中的时区信息。最好使用完整的ISO8601,如“2017-05-17T08:27:27.0314698Z”(dateTime.ToString("o"),更多信息 - Given a DateTime object, how do I get an ISO 8601 date in string format?,或者如果您更喜欢图片 - https://xkcd.com/1179/

不要在序列化数据中使用任何特定于文化的格式(如默认ToString()),除非您100%确信所有配置了相同语言环境设置的服务器和解析代码在读取时始终指定相同的文化值。 ISO8601再次是更安全的选择。