oPossum 1,083 Posted August 21, 2014 Share Posted August 21, 2014 This code quickly determines if a date is within daylight savings time (DST). A companion function adjusts the date and time if necessary. There are many ways to determine if a date is within DST. This code begins by checking large time spans (months) and works down to shorter time spans (hours) as necessary. So for most of the year the decision is made very quickly. The worst cases occur on the days of the transition. BCD representation is used for compatibility with most hardware RTC chips. The day of week (T_RTC.dow) must be set properly for this code to work. Day of week is a value of 1 (Sunday) to 8 (Saturday). typedef struct { // RTC data structure uint8_t sec; // uint8_t min; // uint8_t hour; // uint8_t dow; // uint8_t day; // uint8_t month; // uint8_t year; // } T_RTC; // // Starting in 2007, most of the United States and Canada observe DST from the second Sunday in March to the first Sunday in November int rtc_is_dst(T_RTC const * const rtc) // --- Check if time & date are within DST { // if((rtc->month > 0x03) && (rtc->month < 0x11)) return 1; // After March and before November is DST if((rtc->month < 0x03) || (rtc->month > 0x11)) return 0; // Before March or after November is not DST if(rtc->month == 0x03) { // March if(rtc->day > 0x15) return 1; // After second week, is DST if(rtc->day < 0x08) return 0; // Before second week, is not DST const int d = ((rtc->day >> 4) * 10) + (rtc->day & 0x0F); // Integer day of month int s = d - rtc->dow + 1; // Current or previous Sunday as day of month if(s < 8) s += 7; // Make sure Sunday is in second week if(d < s) return 0; // Before Sunday, is not DST if(d > s) return 1; // After Sunday, is DST if((rtc->hour & 0x3F) < 0x02) return 0; // Before 2:00, is not DST return 1; // 2:00 or after, is DST } else { // rtc->month == 0x11 // November if(rtc->day > 0x07) return 0; // After first week, not DST const int d = ((rtc->day >> 4) * 10) + (rtc->day & 0x0F); // Integer day of month int s = d - rtc->dow + 1; // Current or previous Sunday as day of month if(s < 0) s += 7; // Make sure Sunday is in first week if(d < s) return 1; // Before Sunday, is DST if(d > s) return 0; // After Sunday, is not DST if((rtc->hour & 0x3F) < 0x02) return 1; // Before 2:00, is DST return 0; // 2:00 or after, is not DST } // } // // void rtc_adjust_dst(T_RTC * const rtc) // --- Correct RTC structure for DST if necessary { // static const uint8_t dm[19] = { 0, 0x31, 0x28, 0x31, 0x30, 0x31, 0x30, 0x31, 0x31, 0x30, 0, 0, 0, 0, 0, 0, 0x31, 0x30, 0x31 }; if(rtc_is_dst(rtc)) { // If DST ++rtc->hour; // Increment hour if((rtc->hour & 0x0F) > 9) rtc->hour += 6; // Adjust for BCD if(rtc->hour > 0x23) { // If next day rtc->hour = 0; // Set hour to 0 ++rtc->dow; // Increment day of week if(rtc->dow > 7) rtc->dow = 1; // Adjust for wrap around ++rtc->day; // Increment day of month if((rtc->day & 0x0F) > 9) rtc->day += 6; // Adjust for BCD if(rtc->day > dm[rtc->month]) { // Check if next month rtc->day = 0x01; // Wrap to first day of next month ++rtc->month; // Increment month if((rtc->month & 0x0F) > 9) rtc->month += 6; // Adjust for BCD } // } // } // } // bluehash, rampadc and zborgerd 3 Quote Link to post Share on other sites
roadrunner84 466 Posted August 21, 2014 Share Posted August 21, 2014 You do know that DST is very very much country dependent? The days on which DST happens (or day of week, or astronomical events), as well as the amount of shift differ from country to country. Watch The Problem with Time & Timezones - Computerphile on YouTube. Quote Link to post Share on other sites
zborgerd 62 Posted August 21, 2014 Share Posted August 21, 2014 Still, that's nice code for people who can use it. Thanks for posting it! Quote Link to post Share on other sites
sq7bti 20 Posted October 30, 2014 Share Posted October 30, 2014 Formulas for US and EU beginnings and endings of DST: For the United States:Begin DST: Sunday April (2+6*y-y/4) mod 7+1End DST: Sunday October (31-(y*5/4+1) mod 7)Valid for years 1900 to 2006, though DST wasn't adopted until the 1950s-1960s. 2007 and after:Begin DST: Sunday March 14 - (1 + y*5/4) mod 7End DST: Sunday November 7 - (1 + y*5/4) mod 7; European Economic Community:Begin DST: Sunday March (31 - (5*y/4 + 4) mod 7) at 1h U.T.End DST: Sunday October (31 - (5*y/4 + 1) mod 7) at 1h U.T.Since 1996, valid through 2099 (Equations by Wei-Hwa Huang (US), and Robert H. van Gent (EC)) taken from http://www.webexhibits.org/daylightsaving/i.html kodi and bluehash 2 Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.