'Convert DateTime to DateTimeOffset taking into account SummerTime
Consider the code below. I have a list of dates around the point in time when CEST changes from summer to winter time. I need to convert them to UTC. However using this code the midnight gets lost, I can't understand how to fix it.
DateTime firstDate = new DateTime(2020, 10, 24, 21, 0, 0);
DateTime lastDate = new DateTime(2020, 10, 25, 3, 0, 0);
DateTime[] dates = Enumerable.Range(0, (lastDate - firstDate).Hours + 1)
.Select(r => firstDate.AddHours(r))
.ToArray();
TimeZoneInfo tzo = TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time");
List<DateTimeOffset> offsets = new List<DateTimeOffset>();
foreach(var date in dates)
{
var timeSpan = tzo.GetUtcOffset(date);
var offset = new DateTimeOffset(date, timeSpan);
offsets.Add(offset);
}
10/24/2020 09:00:00 PM +02:00 = 19:00Z
10/24/2020 10:00:00 PM +02:00 = 20:00Z
10/24/2020 11:00:00 PM +02:00 = 21:00Z
10/25/2020 12:00:00 AM +02:00 = 22:00Z
10/25/2020 01:00:00 AM +02:00 = 23:00Z
10/25/2020 02:00:00 AM +01:00 = 01:00Z - What happened to 00:00Z?
10/25/2020 03:00:00 AM +01:00 = 02:00Z
Solution 1:[1]
The problem is that there are two 2AM's on 25th October 2020 - 02:00 AM +02:00 and 02:00 AM +01:00.
Since the source DateTime has no offset available, the GetUtcOffset method has no way to determine which 2AM the value refers to, and so it defaults to using the non-DST offset - 02:00 AM +01:00.
Depending on what you're actually trying to do, you may be able to resolve this by converting the start time to UTC, generating a list of UTC DateTimeOffset values, and then converting them back to the desired time-zone:
DateTime firstDate = new DateTime(2020, 10, 24, 21, 0, 0);
TimeZoneInfo tzo = TimeZoneInfo.FindSystemTimeZoneById("Central European Standard Time");
DateTimeOffset firstDateUtc = TimeZoneInfo.ConvertTime(firstDate, tzo, TimeZoneInfo.Utc);
DateTimeOffset[] utcDates = Enumerable.Range(0, 7).Select(r => firstDateUtc.AddHours(r)).ToArray();
DateTimeOffset[] offsets = Array.ConvertAll(utcDates, d => TimeZoneInfo.ConvertTime(d, tzo));
Output:
24/10/2020 21:00:00 +02:00
24/10/2020 22:00:00 +02:00
24/10/2020 23:00:00 +02:00
25/10/2020 00:00:00 +02:00
25/10/2020 01:00:00 +02:00
25/10/2020 02:00:00 +02:00
25/10/2020 02:00:00 +01:00
Alternatively, you might want to look at NodaTime, which provides a much clearer model for working with dates and times.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Richard Deeming |
