仅从日期开始计算夏令时

Mug*_*ggz 17 datetime arduino dst

我正在使用Arduino和实时时钟芯片.芯片可以补偿闰年等,所以它总是有正确的日期,但它不能处理夏令时,我认为由于区域复杂性.时钟可以给我一天,一个月和一年(基于1)和星期几(星期日= 0到星期六= 6).

因为我需要与用户输入的日期和时间进行比较,我需要知道为夏令时调整的日期和时间.如果当前日期是夏令时我可以简单地从时钟上加一小时到达我需要的东西.

困难的部分是确定我是否在夏令时,因为它每年都在变化.我只关心它在我的位置(山区时间)有效.我的平台似乎没有任何全面的日期库,我觉得无论如何都会有点过头了.是否有一个简单的公式来确定我是否在使用DST?

cap*_*aig 43

这实际上看似简单.有一些事实可以帮助我们:

  1. 在美国的大部分地区,夏令时从3月的第二个星期日开始,到11月的第一个星期日,凌晨2点结束.
  2. 3月的第二个星期日将始终在8日至14日之间.
  3. 11月的第一个星期日将始终在1日至7日之间.
  4. 星期几的编号非常方便,因为星期几将为您提供上周日.

这些事实导致以下代码(C#,但可以轻松地移植到您的平台):

    public bool IsDST(int day, int month, int dow)
    {
        //January, february, and december are out.
        if (month < 3 || month > 11) { return false; }
        //April to October are in
        if (month > 3 && month < 11) { return true; }
        int previousSunday = day - dow;
        //In march, we are DST if our previous sunday was on or after the 8th.
        if (month == 3) { return previousSunday >= 8; }
        //In november we must be before the first sunday to be dst.
        //That means the previous sunday must be before the 1st.
        return previousSunday <= 0;
    }
Run Code Online (Sandbox Code Playgroud)

事实证明,你甚至不需要知道这一年的时间,只要你可以相信你的一周中的价值.

我写了一个快速的单元测试并验证了这段代码同意TimeZone.IsDayLightSavingsTime()所有日期从1800到2200.我没有考虑到凌晨2点的规则,但你可以很容易地检查一周中的星期几是星期日,日期介于两者之间8和14(3月)或1和7(11月).

  • 如果该代码确实与从 1800 年到 2006 年的所有日期的“TimeZone.IsDayLightSavingsTime()”一致,则“TimeZone.IsDayLightSavingsTime()”就被破坏了。直到 1966 年,美国才在全国范围内实行夏令时(两次世界大战期间的某些时期除外)。直到 2007 年,夏令时开始于 4 月的第一个星期日,结束于 10 月的最后一个星期日,除了 1974 年至 1975 年期间全年实行夏令时。 (2认同)

小智 11

中欧代码(2014-3000年范围内每天测试)

    public static bool IsDst(int day, int month, int dow)
    {
        if (month < 3 || month > 10)  return false; 
        if (month > 3 && month < 10)  return true; 

        int previousSunday = day - dow;

        if (month == 3) return previousSunday >= 25;
        if (month == 10) return previousSunday < 25;

        return false; // this line never gonna happend
    }
Run Code Online (Sandbox Code Playgroud)

测试功能

    static void Main(string[] args)
    {
        TimeZoneInfo tzf2 = TimeZoneInfo.FindSystemTimeZoneById("Central Europe Standard Time");

        var date = new DateTime(2014, 01, 1, 5, 0,0);
        bool wasSummer = false;

        while (date <= new DateTime(3000,1,1))
        {                                         
            var dow = (int) date.DayOfWeek;

            var isDst = IsDst(date.Day, date.Month, dow);               

            DateTime f2 = TimeZoneInfo.ConvertTime(date, tzf2);
            var isSummer = f2.IsDaylightSavingTime();

            if (isSummer != isDst)
            {
                Console.WriteLine("ERROR");
                Console.WriteLine(date);
            }

            if (isSummer != wasSummer)
            {
                Console.WriteLine(date.AddDays(-1).ToShortDateString());
            }

            date = date.AddDays(1);
            wasSummer = isSummer;
        }

        Console.ReadKey();
Run Code Online (Sandbox Code Playgroud)

}