The Arduino and Daylight saving time

wintertijd It is that time of the year again that many countries will end the Daylight Saving Time.
But what about your microcontroller? Many programs on the arduino and other microcontrollers keep time and do that with one of the popular RTC chips such as the DS1307 or the DS3231. They keep time very well (but I prefer the DS3231) and there are a hoist of libraries available for them.
One thing they do not do is to automatically between standard time and daylight saving time (DST). Obviously that would be quite hard as  there are different DST conditions all over the world

Though one could of course reset the RTC chip manually twice a year but that is tedious, especially while it can easily be solved with a few lines of code.

Different parts of the world have different rules for when the daylight saving time takes place and many countries of course have no daylight saving: It only makes sense (if at all) to do it between the tropics and the Arctic circles, so in fact between the tropic of Cancer and the Arctic circle and the tropic of Capricorn and the Antarctic circle.

In Australia daylight saving time is a matter of the states and territories but in general daylight saving time is between the first sunday in oktober and the first Sunday in April (remember, it is down under)

In Canada it largely depends on where you live, some states follow the United states. Newfoundland en Nunavut have their own rule and many of the northern territories do not have daylight saving time

The USA has daylight saving time from the 2nd Sunday of March till the first Sunday of November.

The EU of course has a guideline on it that determines the daylight saving time to start on the last Sunday of March and to end on the last Sunday of October. In the EU the hour to switch is at 01:00 UTC. In practice UTC is equal to GMT (Greenwich Mean Time). UTC itself is not an abbreviation but a compromise between the French abbreviation “TUC” and the English “CUT” (Temps Universel Coordonné resp Coordinated Universal Time).

Catering for your local daylight savings program is usually quite easy:
Let your program check for the proper month and then count the number of Sundays (the change is usually on a Sunday). When you arrived at the
required Sunday check the time and if it is say 2 am, advance the clock an hour (=set it to 3) if DST has to start, or wait till 3 am and reset the clock hours to ‘2’.
Obviously you also need to set a flag to do the clock correction only once.

Simple enough… Unless you live in the EU (or Nunavut). In the EU the switch isn’t made at the first, second, third or fourth Sunday in March resp. October, but at the LAST Sunday of the month.

Well, a month has four Sundays right? Wrong. If for instance October starts on a Friday, Saturday or Sunday, it has 5 Sundays. So what to do?
Well you could of course determine if the first day starts on Friday, Saturday or Sunday and if so, count to 5 and otherwise count to 4. But there is a simpler way, in which you don’t even have to count.

Lets put that in a program for Western Europe, which means that the switch times are 2 and 3 am (that is 1:00 UTC)

Let’s agree that you have an RTC that will keep the “day of week” *as the DS1307 and the DS3231 do). As you set these yourself lets agree that you have set the day of week such that Monday is day 1 and Sunday is day 7. Some people like to start the week on Sunday, but that is just a matter of taste.
Anyway, we have the following variables read from our RTC
dow= day of week (as in 1-7)
d=day (as in 1-31)
DST is a flag we set when DST starts and that we clear at the end of DST to avoid that the program starts correcting the time for a full hour and even getting in an endless loop when we set the clock back
As October has 31 days, we know that the last Sunday will always fall from the 25th to the 31st
So our check at the end of daylight saving will be as follows:

if (dow == 7 && mo == 10 && d >= 25 && d <=31 && h == 3 && DST==1)
setclockto 2 am;

As you may be using different libraries the command ‘setclockto 2 am’ is just a place holder for your specific routine to set your RTC to 2 am. I would advise to store the DST flag somewhere in non volatile memory, in case you need to unplug your arduino.
The DS1307 has some on chip Non Volatile RAM where you can store it, the DS3231 does not. Both however usually come as a module with an EEPROM on it as well, otherwise the EEPROM of the Arduino can be used.

Anyway lets do a check if we have the right routine:
Suppose October 1 is a Sunday. That means the 25th is a Wednesday and the 29th a Sunday (the last and 5th Sunday), so the routine will indeed be activated on the 29th as all conditions are met.
Suppose October starts on a Monday. That means there are only 4 Sundays and the last Sunday will fall on the 28th. Again, that is between 25 and 31 so the condition is met.
Suppose October first falls on a Thursday, then the 25th will be a Sunday (the fourth Sunday) and the 31st will be a Saturday, so again the condition will be met for the last (and in this case 4th Sunday).

To start summertime/daylightsaving time on the last Sunday in March is mutatis mutandis the same:

if (dow == 7 && mo == 3 && d >= 25 && d <=31 && h ==2 && DST==0)
setclockto 3 am;

March also has 31 days so the calculations are the same. This time though we check at 2 am and a reset DST flag and then set the clock to 3 am and set the DST flag to indicate it is done already.

Now if you do NOT use an RTC that keeps the day of week or if you keep track of time and date in some other way than with an RTC, then there is an easy formula to determine the day of the week from the date with Sakamoto’s Algorithm

//gives day of week for a given date Sunday=0, Saturday=6
int dow(int y, int m, int d)
static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
y -= m < 3;
return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;

mind you though that this routine counts from 0 (Sunday) to 6 (Saturday)

So when is it Dark?
Suppose that you do not have an LDR in your circuit but you do want your program to know when the sun sets. There are several algorithms to determine that and it depends where on earth you are.
Of course one could store all the sunset times in EEPROM but that would be quit some work and as the DST is on a different date each year, such a table would only be valid for one year.
For my latitude I use a couple of simple formulas that approach the time of sunset fairly accurate. If we look at October and  my RTC returns the  day of the month  as ‘d’, then the formula  looks like this:
case 10:
sunsethour = 18;
sunsetminute=76-2 * d;
if (d < 9)
sunsethour = 19;
sunsetminute = 18 - 2 * d;
if (d >=wintertimeday) (for 2015 this is 25)
sunsethour = 17;

The variable  ‘wintertime day’ we get by expanding our previous method of determining DSt like this:
if (dow == 7 && mo == 10 && d >= 25 && d <=31 && h == 3 && DST==1)
setclockto 2 am;

Oktober Real Sunset Calculated Sunset
1 19:18 19:16
2 19:16 19:14
3 19:13 19:12
4 19:11 19:10
5 19:09 19:08
6 19:06 19:06
7 19:04 19:04
8 19:02 19:02
9 19:00 18:58
10 18:57 18:56
11 18:55 19:54
12 18:53 18:52
13 18:51 18:50
14 18:48 18:48
15 18:46 18:46
16 18:44 18:44
17 18:42 18:42
18 18:40 18:40
19 18:38 18:38
20 18:35 18:36
21 18:33 18:34
22 18:31 18:32
23 18:29 18:30
24 18:27 18:28
25 17:25 17:26
26 17:23 17:24
27 17:21 17:22
28 17:19 17:20
29 17:17 17:18
30 17:15 17:16
31 17:13 17:14

That is fairly accurate and gives a deviation of max 2 minutes (at least for 2015 and on my latitude and longitude. The calculation will still be fairly accurate for years to come).

If you want to come up with a formula for your specific area, then just  get your local sunset table and have a look at what simple suntraction or addition would give you the closest time. Usually, if  you are between the Tropics and the Arctic, the sunset time in the winter and in the summer does not vary that much, and if you are in the tropics, the time doesnt vary that much at all.
As example, my  formula for january:
case 1:
sunsethour = 16;
sunsetminute = 38 + d;
if (d > 16)
sunsethour = 17;
sunsetminute = d - 16;

It IS possible to calculate the sunset (or sunrise) for any place on earth for any date, but believe me, you dont want to do that.