3

我已经阅读了很多 SO 文章,但我似乎无法找到问题的好答案。发布的建议包括将日期转换为字符串或从字符串转换多次的函数,最后连接位,这一切似乎......混乱

那么问题来了:

我们在世界各地都有服务器。所有服务器都以自己的本地时间运行,并保留带有服务器本地时间条目的日志。一些服务器在 DST 观察区域,其他服务器不在

假设我有来自日志的这些字符串:2013-01-01 12:34:56, 2013-07-01 12:34:56 我知道这个服务器在纽约,所以它是 UTC-5 或 UTC-4 时夏令时正在运行

而且我在香港的服务器上的日志中有相同的字符串,其中 DST 不适用,时区为 +8

我所追求的是一段代码,我可以告诉它:

  • 这是一个代表时间的字符串
  • 这是字符串来自的时区
  • 如果相关,应适用夏令时

并且代码会将字符串解析为 DateTimeOffset,如果解析的时间与 DST 相关,则根据 DST 调整偏移量

例如:NY 服务器日志显示“ 2013-01-01 ...”DST不适用于 1 月的这个日期,因此解析的日期应该是:纽约时间 12:34:56,又名 17:34:56 UTC(因为它是 -5,没有 DST)

纽约服务器日志显示“ 2013-07-01 ...”DST确实适用于 6 月的这个日期,因此解析的日期应该是:纽约时间 12:34:56,也就是 UTC 时间 16:34:56(因为它是-4,有夏令时)

香港服务器,两个日期时间都解析为 04:34:56 UTC

多谢你们

4

2 回答 2

6

首先,我强烈建议您更改系统以在任何地方登录 UTC。它会让你的生活变得更简单。

如果你真的DateTime.TryParseExact坚持你所拥有的,你应该DateTimeStyles只使用 0(默认值)。这将为您提供 a DateTimeKindof的值Unspecified,这就是您想要的。(它不是 UTC,也不是进行解析的机器本地的。)

然后,您可以使用TimeZoneInfo.GetUtcOffset(使用该日志的正确时区)计算偏移量,并DateTimeOffset从两者中创建一个。

除了完全有偏见之外,您还可以更改为使用我维护的Noda Time项目,这将使您的代码更易于理解:)

于 2013-02-06T18:26:54.693 回答
5

要获取不同日志文件中记录的时间的 UTC 时间,您需要知道本地时区的名称。然后您可以使用DateTimeOffset-struct TimeZoneInfo-class来计算 UTC 时间:

public DateTime ParseAsUtc(string logDate, string timezoneName)
{
    var timeZone = TimeZoneInfo.FindSystemTimeZoneById(timezoneName);
    var localDate = DateTime.Parse(logDate);
    var offset = new DateTimeOffset(localDate, timeZone.GetUtcOffset(localDate));
    return offset.ToUniversalTime().DateTime;
}

ParseAsUtc("2013-01-01 12:34:56", "Eastern Standard Time"); //01.01.2013 17:34:56
ParseAsUtc("2013-07-01 12:34:56", "Eastern Standard Time"); //01.07.2013 16:34:56
ParseAsUtc("2013-01-01 12:34:56", "China Standard Time");   //01.01.2013 04:34:56
ParseAsUtc("2013-01-01 12:34:56", "China Standard Time");   //01.07.2013 04:34:56
于 2013-02-06T19:02:43.740 回答