.net adds one hour to summer dst [duplicate]

我的梦境 提交于 2019-12-11 09:52:07

问题


I'm getting a following string from a web service 2013-10-15T12:54:18+01:00. This date is in the summer DST and my .NET code (web service proxy, I presume) automatically adds one hour to it. The same is not the case if the returned value falls withing the winter DST. The time returned (12:54:18) is what I want to display, I don't want any sort of recalculation to be done.

I'm using TimeSpan DateTime.TimeOfDay to show the time.

What can I do to make it happen?


回答1:


I am trying to put the pieces together from your question and the additional comments. So far this is my analysis:

  1. On the wire you see two different date and time strings:

    • Without daylight savings (winter) the string is 2013-12-30T12:54:18

    • With daylight savings (summer) the string is 2013-10-15T12:54:18+01:00

    This is a sign that the web service is using GMT Standard Time as the time zone.

  2. You want to extract the GMT timestamp from the date and time string.

  3. However, between you and the web service there is some unspecified web service proxy (I assume some kind of .NET framework?) and in your code you only have access to a DateTime and furthermore your code is executing in the Central Europe Standard Time time zone which basically is one hour ahead of GMT both during summer and winter if we disregard the short time where there is a transition to and from daylight savings.

I hope I am correct so far.

You can convert the incoming DateTime to GMT using this code:

// 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);

This example gives the correct answer during daylight savings. The incoming date and time string contains an offset and is correctly parsed into a local time zone (CET). The TimeZoneInfo.ConvertTime assumes that the source DateTime is in the local time zone and the result is correct.

However, the code fails during winter where there is no daylight savings:

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

Notice that the date and time string no longer contains a time zone offset. The offset is +00:00 but for some reason it is missing from the string. This means that the source DateTime is assumed to be in the local time zone (CET) and not converted from the actual time zone (GMT). This is the source of your problem if my analysis is correct.

Another way to explain it:

       | 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

There is no easy fix for this problem. If you could persuade the web service to provide the correct offset even when it is +00:00 my code above would work both summer and winter. Even better, only use UTC and only convert to a local time when the end-user gets involved. But I guess that you have no control over the web service?

One option would be to execute your code in the same time zone as the server (e.g. GMT). Then you should be able to use the timestamp directly without any conversion.

Another more ugly option is to determine if the web service is outside daylight savings and then adjust the time accordingly:

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);

I have tried to keep the code as general as possible but actually it is only trying to fix the situation where +00:00 is missing and in that case destinationTimeZoneInfo.BaseUtcOffset is precisely 0 so it might be slightly overkill to do it like this.

More importantly, I am not sure that this code provides the correct results during the time when there is a daylight savings transition. Even though I believe that GMT and CET transitions at the same date CET is still one hour ahead of GMT. You really have to create some unit tests to make sure you get the desired result.




回答2:


A DateTime object does not contain offset in this kind of example. It only holds a kind which could be i.e.: local offset (offset of the runtime environment) or UTC. Do it like so, since DateTimeOffset is what you want:

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

Will output

12:54:18
11:54:18



回答3:


You might want to check this MSDN article which describes the transitions that your TimeOfDay is currently returning.

By examining that article, you can find the way on how to correct it. TimeZoneInfo is the class that you'll need.

Edit, the work that Jon Skeet provided might help as well, look at the Noda Time blogspot for more info!



来源:https://stackoverflow.com/questions/27904806/net-adds-one-hour-to-summer-dst

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!