简体   繁体   中英

How to create a TimeZone object for a specific timezone? c#

I found the exact thing I went to know, and it is so simple (or should be):

TimeZone.GetDaylightChanges() returns exactly what I need: When the daylight time starts and ends:

To that end, I would want to do:

TimeZoneInfo currentTimezone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneName);
TimeZone zone = new TimeZone (currentTimezone);  // Compile error here.

DaylightTime changes = zone.GetDaylightChanges();

This, of course won't compile because the constructor of the TimeZone doesn't take a TimeZoneInfo (Wtf?), and I can't figure out how to get the DaylightTime Changes any other way. I need for someone to set 'timeZoneName' to any timezone and be able to get the start/end DateTimes for whatever timezone they set it to.

Of Key importance: The server is running (most likely) UTC, and NOT the timezone that is in 'timeZoneName'

Unfortunately, you can't instantiate a new TimeZone object like that. However, I believe you can get the info you want from the TimeZoneInfo class by looking through the AdjustmentRules .

Below are a few methods that I wrote to enable what you want. See the sample usage at the bottom for how it compares to using the TimeZone method for the current system time zone.

UPDATE

I've modified the code into a couple of classes to help out with the date math, and borrowed heavily from the sample here: https://msdn.microsoft.com/en-us/library/system.timezoneinfo.transitiontime.isfixeddaterule.aspx

public static DaylightTime GetDaylightChanges(string timeZoneName, int year)
{
    TimeZoneInfo currentTimezone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneName);

    var currentRules =
        currentTimezone.GetAdjustmentRules().FirstOrDefault(rule =>
            rule.DateStart <= DateTime.Today &&
            rule.DateEnd >= DateTime.Today);

    if (currentRules != null)
    {
        var daylightStart = 
            GetTransitionDate(currentRules.DaylightTransitionStart, year);

        var daylightEnd = 
            GetTransitionDate(currentRules.DaylightTransitionEnd, year);

        return new DaylightTime(daylightStart, daylightEnd, 
            currentRules.DaylightDelta);
    }

    return null;
}

private static DateTime GetTransitionDate(TimeZoneInfo.TransitionTime transition, 
    int year)
{
    return (transition.IsFixedDateRule)
        ? new DateTime(year, transition.Month, transition.Day,
            transition.TimeOfDay.Hour, transition.TimeOfDay.Minute,
            transition.TimeOfDay.Second)
        : GetNonFixedTransitionDate(transition, year);
}

private static DateTime GetNonFixedTransitionDate(
    TimeZoneInfo.TransitionTime transition, int year)
{
    var calendar = CultureInfo.CurrentCulture.Calendar;
    int startOfWeek = transition.Week * 7 - 6;
    int firstDayOfWeek = (int) calendar.GetDayOfWeek(new DateTime(year, 
        transition.Month, 1));

    int changeDayOfWeek = (int) transition.DayOfWeek;

    int transitionDay = (firstDayOfWeek <= changeDayOfWeek) 
        ? startOfWeek + (changeDayOfWeek - firstDayOfWeek)
        : startOfWeek + (7 - firstDayOfWeek + changeDayOfWeek);

    if (transitionDay > calendar.GetDaysInMonth(year, transition.Month))
        transitionDay -= 7;

    return new DateTime(year, transition.Month, transitionDay, 
        transition.TimeOfDay.Hour, transition.TimeOfDay.Minute, 
        transition.TimeOfDay.Second);
}   

And here's and example of how to use it, compared to using the current TimeZone method:

public static void Main()
{
    var daylightTime = GetDaylightChanges("Pacific Standard Time", DateTime.Today.Year);
    var dylightTime2 = TimeZone.CurrentTimeZone.GetDaylightChanges(DateTime.Today.Year);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM