Calculating daylight saving time from only date

后端 未结 9 1747
春和景丽
春和景丽 2021-01-31 10:53

I am working with an Arduino and a real time clock chip. The chip compensates for leap years and such, so it will always have the correct date, but it does not handle daylight s

9条回答
  •  名媛妹妹
    2021-01-31 11:19

    I found this all very helpful. Brazil has some special issues, southern hemisphere, and sometimes Carnival overlaps the fall change date.

    In these cases, the legislature delays DST by one week. The US Naval observatory calculation can find easter, (at http://aa.usno.navy.mil/faq/docs/easter.php, retrieved 1/3/2017), and carnival is an exact number of days earlier, the week-end before ash wednesday (Mardi Gras means "fat tuesday").

    So, in C:

        static const uint8_t carnival[] = {
        0x04, 0x24, 0x24, 0x21, // 2000... 2031 
        0x01, 0x09, 0x48, 0x09, // 2032... 2063
        0x4a, 0x40, 0x4a, 0x52, // 2064... 2095
        0x02, 0x90, 0x12, 0x94  // 2096... 2127
        }
    
    /* Returns the current time offset. */
    
    int dst(struct tm *tm_ptr)
    {
    
        int st = 0;
        int dst = 60;
        int mon = tm_ptr->tm_mon;
        int mday, previous_sunday;
        int gmt_offset = tm_ptr->gmt_offset;
    
        // If not Brasilia or Amazon time, no DST.
        if(gmt_offset != -240 && gmt_offset != -300)
            return st;
    
        if(NOV < mon || FEB > mon) // Summer?
            return dst;
        else if(NOV > mon && FEB < mon) // Winter?
            return st;
    
        mday = tm_ptr->tm_mday;
    
        previous_sunday = mday - tm_ptr->tm_wday;
        // Begin DST on first Sunday of November.
        if(NOV == mon) // If it's November... i.e. spring, so forward
        {
            if(previous_sunday < 1) // Before Sunday, week 1?
            {
                return st;
            } else { // After or during Sunday, week 1
                return dst;
            }
            // End DST in February, accounting for Carnival.
        } else { // It has to be February, i.e. fall, so backward.
            int year, week_start;
    
            year = tm_ptr->tm_year;
            if(0 == (carnival[year/8] & (1 << (year%8))))
                week_start = 15; // 3rd Sunday is not in Carnival.
            else
                week_start = 22; // Use 4th Sunday, 1 week after Carnival.
    
            if(previous_sunday < (week_start-1))
                return dst;
            if(previous_sunday < week_start) {
                if(tm_ptr->tm_isdst == st) // if it already fell backward, stay.
                    return st;
                return dst;
            }
            // On or after the correct Sunday?
            return st;
        }
    }
    

提交回复
热议问题