.net 夏令时增加一小时

.net adds one hour to summer dst

我从 Web 服务 2013-10-15T12:54:18+01:00 获得以下字符串。这个日期是夏季夏令时,我的 .NET 代码(我认为是 Web 服务代理)会自动向其添加一个小时。如果返回值属于冬季 DST,则情况不同。返回的时间 (12:54:18) 是我想要显示的,我不想进行任何类型的重新计算。

我正在使用 TimeSpan DateTime.TimeOfDay 显示时间。

我该怎么做才能实现它?

您可能需要检查 this MSDN article,它描述了您的 TimeOfDay 当前返回的转换。

通过查看那篇文章,您可以找到更正它的方法。 TimeZoneInfo 是您需要的 class。

编辑,Jon Skeet 提供的工作也可能有所帮助,查看 Noda Time blogspot 了解更多信息!

在此类示例中,DateTime 对象不包含偏移量。它只包含一个 kind ,它可以是:本地偏移量(运行时环境的偏移量)或 UTC。这样做吧,因为 DateTimeOffset 是你想要的:

DateTimeOffset test = DateTimeOffset.Parse("2013-10-15T12:54:18+01:00");

Console.WriteLine(test.DateTime.TimeOfDay); // UTC
Console.WriteLine(test.LocalDateTime.TimeOfDay); // Localized with the offset parsed

会输出

12:54:18
11:54:18

我正在尝试将您的问题和其他评论中的各个部分拼凑起来。到目前为止,这是我的分析:

  1. 在线路上您看到两个不同的日期和时间字符串:

    • 没有夏令时(冬季)字符串是 2013-12-30T12:54:18

    • 夏令时(夏季)字符串为 2013-10-15T12:54:18+01:00

    这表明 Web 服务正在使用 GMT 标准时间 作为时区。

  2. 您想从日期和时间字符串中提取 GMT 时间戳。

  3. 但是,在您和 Web 服务之间有一些未指定的 Web 服务代理(我假设是某种 .NET 框架?)并且在您的代码中您只能访问 DateTime 并且您的代码在 中欧标准时间 时区执行,如果我们在夏季和冬季基本上比格林威治标准时间早一小时忽略夏令时转换的短暂时间。

我希望到目前为止我是正确的。

您可以使用此代码将传入的 DateTime 转换为 GMT:

// Framework code creates the DateTime.
var sourceDateTime = DateTime.Parse("2013-10-15T12:54:18+01:00");
// Application code can further process the DateTime.
var destinationTimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
var destinationDateTime = TimeZoneInfo.ConvertTime(sourceDateTime, destinationTimeZoneInfo);

这个例子在夏令时给出了正确答案。传入的日期和时间字符串包含一个偏移量,并被正确解析为本地时区 (CET)。 TimeZoneInfo.ConvertTime 假定源 DateTime 在本地时区并且结果是正确的。

但是,代码在没有夏令时的冬季失败:

var sourceDateTime = DateTime.Parse("2013-12-30T12:54:18");

请注意,日期和时间字符串不再包含时区偏移量。偏移量是 +00:00 但由于某种原因它从字符串中丢失。这意味着源 DateTime 假定为本地时区 (CET),而不是从实际时区 (GMT) 转换而来。 如果我的分析是正确的,这就是你问题的根源。

另一种解释方式:

       | Server (GMT)  | Framework (CET)           | My code
-------+---------------+---------------------------+----------------------------
Summer | +01:00 suffix | GMT -> CET adds 1 hour    | CET -> GMT subtracts 1 hour
-------+---------------+---------------------------+----------------------------
Winter | No suffix     | Assumed to be CET         | CET -> GMT subtracts 1 hour

这个问题没有简单的解决办法。如果您可以说服 Web 服务提供正确的偏移量,即使它是 +00:00,我上面的代码也可以在夏季和冬季使用。更好的是,仅使用 UTC 并且仅在最终用户参与时才转换为本地时间。但我猜你无法控制网络服务?

一种选择是在与服务器相同的时区(例如 GMT)执行您的代码。那么你应该可以直接使用时间戳而不需要任何转换。

另一个更难看的选项是确定网络服务是否在夏令时之外,然后相应地调整时间:

var destinationTimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
if (!destinationTimeZoneInfo.IsDaylightSavingTime(sourceDateTime)) {
  var sourceDateTimeOffset = new DateTimeOffset(sourceDateTime, destinationTimeZoneInfo.BaseUtcOffset);
  sourceDateTime = sourceDateTimeOffset.UtcDateTime;
}
var destinationDateTime = TimeZoneInfo.ConvertTime(sourceDateTime, destinationTimeZoneInfo);

我试图使代码尽可能通用,但实际上它只是试图修复缺少 +00:00 的情况,在这种情况下 destinationTimeZoneInfo.BaseUtcOffset 正好是 0,所以它可能是这样做有点矫枉过正。

更重要的是,我不确定这段代码在夏令时转换期间是否提供了正确的结果。尽管我相信 GMT 和 CET 在同一天过渡,但 CET 仍然比 GMT 早一小时。您确实必须创建一些单元测试以确保获得所需的结果。