43oh

# Daylight Saving Time detection and adjustment

## Recommended Posts

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
}                                                 //
}                                                   //
}                                                     //
}                                                       //
```
##### Share on other sites

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.

##### Share on other sites

Still, that's nice code for people who can use it.  Thanks for posting it!

##### Share on other sites
• 2 months later...

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+1
End 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 7
End 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))

## Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

Only 75 emoji are allowed.

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
• Blog

• #### Activity

×
• Create New...