Quantcast
Channel: MSP430 Technical Forums
Viewing all articles
Browse latest Browse all 2077

Daylight Saving Time detection and adjustment

$
0
0
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
      }                                                 //
    }                                                   //
  }                                                     //
}                                                       //

Viewing all articles
Browse latest Browse all 2077

Trending Articles