Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get UTC Offset during DST time in .NET

I am trying to get all offsets seen in a timezone, in an interval. Below is the function that I used to accomplish this, I know you could use TimeZoneInfo.BaseUtcOffset to get the UTC offset for a timezone during standard time, but there is no similar method to get one during daylight saving time unless you pass a particular DST point of time to the GetUTCOffset() method.

static void GetOffsets(DateTime startTime, DateTime endTime, TimeZoneInfo tz)
{
    var result = new HashSet<int>();
    var adjRules = tz.GetAdjustmentRules();
    result.Add(tz.BaseUtcOffset);

    foreach (var adjustmentRule in adjRules)
    {
        if ((startTime >= adjustmentRule.DateStart && startTime <= adjustmentRule.DateEnd) || (endTime >= adjustmentRule.DateStart && endTime <= adjustmentRule.DateEnd) ||
             (stTime <= adjustmentRule.DateStart && endTime >= adjustmentRule.DateEnd))
        {
            if(adjustmentRule.DaylightDelta != TimeSpan.Zero)
            {
                if (!result.Contains(tz.BaseUtcOffset + adjustmentRule.DaylightDelta))
                      result.Add((tz.BaseUtcOffset + adjustmentRule.DaylightDelta));
            }
         }
     }

     foreach (var res in result)
     {
         Console.WriteLine(res);
     }
}

Please let me know if there is a better way to do this.

like image 796
vksp Avatar asked Nov 11 '12 03:11

vksp


Video Answer


1 Answers

I am trying to get all offsets seen in a timezone, in an interval.

I would strongly advise you to avoid trying to use TimeZoneInfo directly. The adjustment rules can be surprisingly awkward for some zones in some years, as I've found to my expense.

While I'm biased, I'd suggest using Noda Time, which can wrap a TimeZoneInfo and do the hard work for you, via BclDateTimeZone.FromTimeZoneInfo. Your question isn't entirely clear in terms of requirements, but if you can say a bit more about what you're trying to do, I can write the appropriate Noda Time code for you.

Your initial description could be implemented with something like this:

public IEnumerable<ZoneInterval> GetZoneIntervalsInInterval
    (this DateTimeZone zone, Interval interval)
{
    Instant current = interval.Start;
    while (current < interval.End && current != Instant.MaxValue)
    {
        ZoneInterval zi = zone.GetZoneInterval(current);
        yield return zi;
        current = zi.End;
    }
}

Then:

var zone = BclDateTimeZone.FromTimeZoneInfo(tzInfo);
var offsets = zone.GetZoneIntervalsInInterval(interval)
                  .Select(zi => zi.WallOffset)
                  .Distinct();

That's assuming that you mean the same thing by "offset" as I do (namely the difference between UTC and local time).

like image 77
Jon Skeet Avatar answered Sep 24 '22 11:09

Jon Skeet