using System.Diagnostics;
using System.Runtime.InteropServices;
public static void Main()
string tzid = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "GMT Standard Time" : "Europe/London";
TimeZoneInfo zone = TimeZoneInfo.FindSystemTimeZoneById(tzid);
ShowDayDuration(new DateTime(2021, 3, 28), zone);
ShowDayDuration(new DateTime(2021, 6, 19), zone);
ShowDayDuration(new DateTime(2021, 10, 31), zone);
public static void ShowDayDuration(DateTime date, TimeZoneInfo zone)
TimeSpan duration = GetDayDuration(date, zone);
Console.WriteLine($"Duration of {date:yyyy-MM-dd} in zone {zone.Id}: {duration.TotalHours} hours");
public static TimeSpan GetDayDuration(DateTime date, TimeZoneInfo zone)
Debug.Assert(date.Kind == DateTimeKind.Unspecified);
Debug.Assert(date.TimeOfDay == TimeSpan.Zero);
DateTimeOffset dto1 = GetStartOfDay(date, zone);
DateTimeOffset dto2 = GetStartOfDay(date.AddDays(1), zone);
public static DateTimeOffset GetStartOfDay(DateTime date, TimeZoneInfo zone)
Debug.Assert(date.Kind == DateTimeKind.Unspecified);
Debug.Assert(date.TimeOfDay == TimeSpan.Zero);
if (zone.IsAmbiguousTime(date))
offset = zone.GetAmbiguousTimeOffsets(date).Max();
while (zone.IsInvalidTime(date))
date = date.AddMinutes(15);
offset = zone.GetUtcOffset(date);
return new DateTimeOffset(date, offset);