I am trying to put the pieces together from your question and the additional comments. So far this is my analysis:
On the wire you see two different date and time strings:
This is a sign that the web service is using GMT Standard Time as the time zone.
You want to extract the GMT timestamp from the date and time string.
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.