Jak zjistit začátek a konec letního času?

Tomáš Holan       22. 10. 2012             5534 zobrazení

Operační systém Windows již několik verzí zpět obsahuje podporu pro změnu letního a standardního času. Pokud by jsme tedy ve své aplikaci potřebovali využít informace týkajících se změny na letní čas (daylight saving time – DST), je možné je získat přímo ze systému. To může být výhodné z toho důvodu, že pokud by došlo ke změně okamžiku, kdy se změna času provádí, Microsoft přes Windows Update vydá aktualizaci, která tuto případnou změnu zohlední a my se nemusíme o nic starat.

Informace o změně na letní čas jsou v systému vztažené k časové zóně. V .NETu jsou pak tyto informace pro libovolnou časovou zónu zpřístupněné od verze 3.5, kde je k dispozici nová třída TimeZoneInfo. Tato třída nám umožňuje získat změny času ve tvarů obecných pravidel (například, že ke změně na letní čas dochází pátou neděli v březnu).

Ukážeme si funkci, která získá kdy letní čas začíná, konči a dobu, o kterou se čas posouvá. Pro to bude potřeba provést převod nalezeného pravidla na konkrétní datum a čas. Vytvořená funkce bude mít jako vstupní parametr požadovaný rok a objekt TimeZoneInfo.

internal static class DaylightTimeUtil
{
    #region action methods
    public static DaylightTime GetDaylightTime(int year, TimeZoneInfo timeZone)
    {
        var rules = timeZone.GetAdjustmentRules();
        if (rules.Length == 0)  //No adjustment rules.
        {
            return null;
        }
        var rule = GetAdjustmentRule(rules, year);
        if (rule == null) //No adjustment rules available for this year.
        {
            return null;
        }

        var startTransition = rule.DaylightTransitionStart;
        int startYear = year;
        var endTransition = rule.DaylightTransitionEnd;
        int endYear = startYear;

        //Does the transition back occur in an earlier month (i.e.,  
        //the following year) than the transition to DST? If so, make 
        //sure we have the right adjustment rule. 
        if (endTransition.Month < startTransition.Month)
        {
            endTransition = GetAdjustmentRule(rules, year + 1).DaylightTransitionEnd;
            endYear++;
        }

        return new DaylightTime(TransitionTimeToDateTime(startYear, startTransition), TransitionTimeToDateTime(endYear, endTransition), rule.DaylightDelta);
    }
    #endregion

    #region private member functions
    private static TimeZoneInfo.AdjustmentRule GetAdjustmentRule(TimeZoneInfo.AdjustmentRule[] rules, int year)
    {
        //Iterate adjustment rules for time zone 
        foreach (TimeZoneInfo.AdjustmentRule rule in rules)
        {
            //Determine if this adjustment rule covers year desired 
            if (rule.DateStart.Year <= year && rule.DateEnd.Year >= year)
            {
                return rule;
            }
        }
        return null;
    }

    private static DateTime TransitionTimeToDateTime(int year, TimeZoneInfo.TransitionTime transition)
    {
        DateTime timeOfDay = transition.TimeOfDay;
        if (transition.IsFixedDateRule)
        {
            int daysInMonth = DateTime.DaysInMonth(year, transition.Month);
            return new DateTime(year, transition.Month, daysInMonth < transition.Day ? daysInMonth : transition.Day, timeOfDay.Hour, timeOfDay.Minute, timeOfDay.Second, timeOfDay.Millisecond);
        }
        DateTime dateTime;
        if (transition.Week <= 4)
        {
            dateTime = new DateTime(year, transition.Month, 1, timeOfDay.Hour, timeOfDay.Minute, timeOfDay.Second, timeOfDay.Millisecond);
            int dayOfWeek = (int)dateTime.DayOfWeek;
            int num = ((int)transition.DayOfWeek) - dayOfWeek;
            if (num < 0)
            {
                num += 7;
            }
            num += 7 * (transition.Week - 1);
            if (num > 0)
            {
                dateTime = dateTime.AddDays(num);
            }
            return dateTime;
        }
        int day = DateTime.DaysInMonth(year, transition.Month);
        dateTime = new DateTime(year, transition.Month, day, timeOfDay.Hour, timeOfDay.Minute, timeOfDay.Second, timeOfDay.Millisecond);
        int num2 = (int)(dateTime.DayOfWeek - transition.DayOfWeek);
        if (num2 < 0)
        {
            num2 += 7;
        }
        if (num2 > 0)
        {
            dateTime = dateTime.AddDays(-num2);
        }
        return dateTime;
    }
    #endregion
}

Použití vytvořené funkce může být pak následující:

var timeZone = TimeZoneInfo.FindSystemTimeZoneById("Central Europe Standard Time");
Console.WriteLine("{0}:", timeZone.DaylightName);

var daylightTime = DaylightTimeUtil.GetDaylightTime(2012, timeZone);
if (daylightTime == null)
{
    Console.WriteLine("No adjustment rules available.");
    return;
}

Console.WriteLine("Start: {0:g}", daylightTime.Start);
Console.WriteLine("End: {0:g}", daylightTime.End);
Console.WriteLine("Delta: {0}", daylightTime.Delta);

Výstup z výše uvedeného kódu je následující:

Central Europe Daylight Time:
Start: 25. 3. 2012 2:00
End: 28. 10. 2012 3:00
Delta: 01:00:00

 

hodnocení článku

0       Hodnotit mohou jen registrované uživatelé.

 

Nový příspěvek

 

                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:  
Heslo:  

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback