TimeZoneInfo AdjustmentRule error on .net core 1.1

I have a piece of code that allows me to get the current date/time (local).

It will be run on Azure.

I'm getting universal time and converting it to local UK time (taking into consideration for BST - British Summer Time).

While migrating from a .NET 4.6.1/Core project to .NET Core 1.1 I'm now faced with a error.

The type name 'AdjustmentRule' does not exist in the type 'TimeZoneInfo'

'TimeZoneInfo' does not contain a definition for 'GetAdjustmentRules' and no extension method 'GetAdjustmentRules' accepting a first argument of type 'TimeZoneInfo' could be found (are you missing a using directive or an assembly reference?)

Using .NET Core 1.1 only - how can I resolve this?

public static DateTime GetLocalDateTimeNow()
{
    DateTime localDate = System.DateTime.Now.ToUniversalTime();

    // Get the venue time zone info
    TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
    TimeSpan timeDiffUtcClient = tz.BaseUtcOffset;
    localDate = System.DateTime.Now.ToUniversalTime().Add(timeDiffUtcClient);

    if (tz.SupportsDaylightSavingTime && tz.IsDaylightSavingTime(localDate))
    {
        TimeZoneInfo.AdjustmentRule[] rules = tz.GetAdjustmentRules();
        foreach (var adjustmentRule in rules)
        {
            if (adjustmentRule.DateStart <= localDate && adjustmentRule.DateEnd >= localDate)
            {
                localDate = localDate.Add(adjustmentRule.DaylightDelta);
            }
        }
    }

    DateTimeOffset utcDate = localDate.ToUniversalTime();

    return localDate;
}

I don't mind replacing the implementation as long as it takes into account BST and runs on .net core 1.1 (without 4.6.1).

Jon Skeet
people
quotationmark

You shouldn't need to do any of this yourself - just ask TimeZoneInfo to do the conversion. That's what it's there for!

// Only need to do this once...
private static readonly TimeZoneInfo londonZone =
    TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");

public static DateTime GetUkDateTimeNow() =>
    TimeZoneInfo.ConvertTime(DateTime.UtcNow, londonZone);

A few notes:

  • I've renamed GetLocalDateTimeNow() to GetUkDateTimeNow() to make it clear that it's always dealing with the UK time zone, not the time zone local to a particular user or computer
  • On Unix, you'd need to ask for "Europe/London" instead of "GMT Standard Time"
  • To make it independent of any of that - and indeed of the system local time zone data - you could use my Noda Time project which I'd like to think will give you generally cleaner code instead.

Almost no-one needs to deal with AdjustmentRule in their code. I do in Noda Time, because I need to be able to represent TimeZoneInfo zones as Noda Time DateTimeZone objects, but that's pretty unusual. If you ever do need to use them, they're far more complicated than you might expect, and there have been several occurrences of bugs in the .NET implementation; I'm currently (as in, today) fighting bugs in the Mono implementation instead...

As an aside, I would strongly urge you not to use DateTime.Now anywhere. Always use DateTime.UtcNow, and then convert into the system local time zone if you really, really need to.

people

See more on this question at Stackoverflow