Determining if currently set time is in daylight savings or not

Hello,

I'm trying to write a piece of code to look at the current time set using the Time.h library, and determine whether or not this point in time is a point of time where daylight savings time is in effect.

For this, I'm not getting fancy with multiple states or countries, I'm just looking at US daylight savings time, in the areas that observe it. (Starts second Sunday in March at 2AM and ends first Sunday in November at 2AM.)

I wrote this code that I think would properly return a 0 or a 1 to indicate if DST is in effect at the currently set time. Does this look right? First, I'm saying if the month is anywhere between March and November, DST should be 1.

Then I check to see if the month is March. If the day is greater than 14, meaning the second Sunday must have already passed, DST is 1. If it's less than 8, meaning the second Sunday couldn't have happened yet, DST is 0. If the day is between those two, then it runs through if statements for each day and checks if the day of the week is Sunday and if the hour is greater than 1. If both of those are the case, it sets DST to 1. Otherwise, it leaves it at 0. (Actually, I guess one of those must be Sunday, so I could probably get rid of the last else.)

Then, it kind of does the inverse if the month is November to determine if the day is within the range that might be the first Sunday in November, and if the day is indeed Sunday, and if the hour is greater than 1, meaning DST should go back to 0.

I'm sure there is a much cleaner way to do this, and I'm probably this code will probably hurt most peoples' eyes. But, at my current skill level, a bunch of nested if statements is all I could come up with to try to test the date to see if it's within the DST time of the year or not. Mainly I just want to see if there is some flaw in my logic here.

Thanks.

if (month() > 3 && month() < 11)
    {
     DST = 1;
    }
else if (month() == 3)
    {
     if (day() > 14)
         {
          DST = 1;
         } 
     else if (day() < 8)
         {
          DST = 0; 
         }
     else if (day() == 8)
           {
            if (weekday() == 1)
              {
                if (hour() > 1)
                 {
                  DST = 1;
                 }
              }
           }   
     else if (day() == 9)
           {
            if (weekday() == 1)
              {
                if (hour() > 1)
                 {
                  DST = 1;
                 }
              }
           }   
      else if (day() == 10)
           {
            if (weekday() == 1)
              {
                if (hour() > 1)
                 {
                  DST = 1;
                 }
              }
           }   
      else if (day() == 11)
           {
            if (weekday() == 1)
              {
                if (hour() > 1)
                 {
                  DST = 1;
                 }
              }
           }   
      else if (day() == 12)
           {
            if (weekday() == 1)
              {
                if (hour() > 1)
                 {
                  DST = 1;
                 }
              }
           }   
      else if (day() == 13)
           {
            if (weekday() == 1)
              {
                if (hour() > 1)
                 {
                  DST = 1;
                 }
              }
           }  
      else if (day() == 14)
           {
            if (weekday() == 1)
              {
                if (hour() > 1)
                 {
                  DST = 1;
                 }                 
              }
           }   
       else
           {
            DST = 0;
           }
    } 
else if (month() == 11)
    {
     if (day() > 7)
         {
          DST = 0;
         } 
     else if (day() == 1)
           {
            if (weekday() == 1)
              {
                if (hour() > 1)
                 {
                  DST = 0;
                 }
              }
           }   
     else if (day() == 2)
           {
            if (weekday() == 1)
              {
                if (hour() > 1)
                 {
                  DST = 0;
                 }
              }
           }   
      else if (day() == 3)
           {
            if (weekday() == 1)
              {
                if (hour() > 1)
                 {
                  DST = 0;
                 }
              }
           }   
      else if (day() == 4)
           {
            if (weekday() == 1)
              {
                if (hour() > 1)
                 {
                  DST = 0;
                 }
              }
           }   
      else if (day() == 5)
           {
            if (weekday() == 1)
              {
                if (hour() > 1)
                 {
                  DST = 0;
                 }
              }
           }   
      else if (day() == 6)
           {
            if (weekday() == 1)
              {
                if (hour() > 1)
                 {
                  DST = 0;
                 }
              }
           }  
      else if (day() == 7)
           {
            if (weekday() == 1)
              {
                if (hour() > 1)
                 {
                  DST = 0;
                 }                 
              }
           }   
       else
           {
            DST = 1;
           }
    }

Go by the number of the day in the year instead of month/year. You only have to correct for leap year

Here is the code I use for the U.S. The DST calculator is in the printClock function. Please feel free to steal what you need from it. I have one for Italy also.

#include <Time.h>

char wkday[7][4] = {"SUN","MON","TUE","WED","THU","FRI","SAT"};

unsigned long nextEpoch = 0UL;
unsigned long testEpoch;
// set time zone for standard time
long timeZone = -6;

void setup() 
{
  Serial.begin(115200);

  Serial.println(F("Ready"));

// Set test time here. UTC/GMT
// hour, minutes, seconds, day, month, year
  setTime(1,0,0,5,3,2015);

  testEpoch = now();  
}

void loop() {

// This checks once a day for long range testing
  testEpoch += 3600UL * 24UL;

// This checks every hour for the switch to and from DST
//  testEpoch += 3600UL;

// This checks every minute for the switch to and from DST
//  testEpoch += 60UL;

  printClock(testEpoch);
  delay(250);
}

void printClock(unsigned long thisEpoch) {
  unsigned long tzEpoch = thisEpoch + (timeZone * 3600UL);
  bool dst = false;

  time_t t = tzEpoch;

  int thisYear = year(t);
  int thisMonth = month(t);
  int thisDay = day(t);
  int thisWeekday = weekday(t);
  int thisHour = hour(t);
  int thisMinute = minute(t);
  
  if(thisMonth == 11 && thisDay < 8 && thisDay < thisWeekday)
  {
    dst=true;
  }
  
  if(thisMonth == 11 && thisDay < 8 && thisWeekday == 1 && thisHour < 1)
  {
    dst=true;
  }

  if(thisMonth < 11 && thisMonth > 3) dst = true;
  
  if(thisMonth == 3 && thisDay > 7 && thisDay >= (thisWeekday + 7))
  {
    if(!(thisWeekday == 1 && thisHour < 2)) dst = true;
  }
  
  if(dst) t += 3600UL; 

  Serial.print(wkday[weekday(t) - 1]);
  Serial.print(" "); 

  if(hour(t) < 10) Serial.print(" ");
  Serial.print(hour(t)); // print the hour (86400 equals secs per day)
  Serial.print(':');  
  // In the first 10 minutes of each hour, we'll want a leading '0'
  if ( minute(t) < 10 ) Serial.print('0');
  Serial.print(minute(t)); // print the minute (3600 equals secs per minute)
  Serial.print(" ");
  Serial.print(month(t));
  Serial.print("-");
  Serial.print(day(t));
  Serial.print("-");
  Serial.print(year(t));
  if(dst) Serial.println(" DST");
  else Serial.println();
}

This seems to work:

  // First, get the year:
  int yy = year - 2000;
  // yy should be e.g. 16 for AD 2016

  // Then calculate:
  int x = (yy + yy/4 + 2) % 7;

  // Then, if date/time is in the period from
  //   02:00:00 on day (14 - x) of March
  // through
  //   00:59:59 on day (7 - x) of November
  // then US Daylight Saving Time is in effect.

odometer suggested something I have not seen before. I had a student do a complete sketch that would set DST TRUE or FALSE. Hope it is documented well enough to be clear

You might consider this code. This method allows you to set the time in standard time without any regard for DST. The following code will determine state of DST and add one hour if required.

This uses a suggestion from odometer to calculate the Sunday offset value

// ********************* Calculate offset for Sunday *********************
int y = year - 2000; // Get year from RTC and subtract 2000
int x = (y + y/4 + 2) % 7; // remainder will identify which day of month
// is Sunday by subtracting x from the one
// or two week window. First two weeks for March
// and first week for November

// *********** Test DST: BEGINS on 2nd Sunday of March @ 2:00 AM *********
if(month == 3 && dayOfMonth == (14 - x) && hour >= 2)
{
DST = 1; // Daylight Savings Time is TRUE (add one hour)
}
if(month == 3 && dayOfMonth > (14 - x) || month > 3)
{
DST = 1;
}
// ************* Test DST: ENDS on 1st Sunday of Nov @ 2:00 AM ************
if(month == 11 && dayOfMonth == (7 - x) && hour >= 2)
{
DST = 0; // daylight savings time is FALSE (Standard time)
}
if(month == 11 && dayOfMonth > (7 - x) || month > 11 || month < 3)
{
DST = 0;
}

if(DST == 1) // Test DST and add one hour if = 1 (TRUE)
{
hour = hour + 1;
}

Arizona does not have DST! Part of Oregon is Pacific time the other part is Mountain. Idaho is same way.

Paul

Actually, the Navaho Nation in Arizona does observe DST.

(Like I say, southern AZ does not need to observe DST, because they have plenty of daylight, they don't need to save any.)

KeithRB:
Actually, the Navaho Nation in Arizona does observe DST.

(Like I say, southern AZ does not need to observe DST, because they have plenty of daylight, they don't need to save any.)

Interesting! DST is a political decision, not a natural one!

Our eldest son was in the first Gulf war. In trying to figure out what the time was in his area, we discovered some of the Middle East was using 1/2 hour DST.

Paul

You could also use an Arduino TimeZone library. I use this (lightly modified) : GitHub - JChristensen/Timezone: Arduino library to facilitate time zone conversions and automatic daylight saving (summer) time adjustments.

SurferTim:
Here is the code I use for the U.S. The DST calculator is in the printClock function. Please feel free to steal what you need from it. I have one for Italy also.

Can you post the one for Italy? It will work for most of Europe.