Introduction: Adding Daylight Savings Time to Your RTC
Having made a little toddler clock for my daughter (just a RGB LED that turns green at 7:30am and red at 7:30pm to let her know the time) I realized in March that it does not have support for Daylight Savings Time.
Since I live in Canada which shares this with most of the United States, our Daylight Savings Time (DST for short) begins on the second Sunday in March and ends on the first Sunday of November.
Below is the code snippet you can add to your RTC project to add support for DST (tested on DS3231 with the RTClib.h library from Adafruit: https://github.com/adafruit/RTClib). It uses Arduino's EEPROM.h library to store the DST flag. It works best if the RTC project is always plugged in (as it updates at 2am) but there is a piece of code in the setup() function that lets you very quickly adjust DST if you miss the time window (if the project is not plugged in all the time) Note that RTClib uses 0 to 6 for days, 0 being Sunday.
#include <EEPROM.h>
#include <RTClib.h>RTC_DS3231 rtc; int DST;
void setup() {
DST = EEPROM.get(0, DST);
if(DST != 0 && DST != 1)
{
DST = 1;
EEPROM.put(0, DST);
}
// Uncomment the following 2 lines if you need to set the DST (if you miss the actual day etc). Change the +1 to -1 in the fall. // DateTime t2 = rtc.now(); // rtc.adjust(DateTime(t2.year(), t2.month(), t2.day(), t2.hour()+1, t2.minute(), t2.second()));
}
void loop() {
DateTime now = rtc.now();
if (now.dayOfTheWeek() == 0 && now.month() == 3 && now.day() >= 8 && now.day() <= 16 && now.hour() == 2 && now.minute() == 0 && now.second() == 0 && DST == 0) {
rtc.adjust(DateTime(now.year(), now.month(), now.day(), now.hour()+1, now.minute(), now.second())); DST = 1; EEPROM.put(0, DST);
} else if(now.dayOfTheWeek() == 0 && now.month() == 11 && now.day() >= 1 && now.day() <= 8 && now.hour() == 2 && now.minute() == 0 && now.second() == 0 && DST == 1) {
rtc.adjust(DateTime(now.year(), now.month(), now.day(), now.hour()-1, now.minute(), now.second())); DST = 0; EEPROM.put(0, DST);
}
}
7 Comments
Question 2 years ago
Hi, Thanks for the cool code. I was a little lost as to the now.day >= 8 and <= 16. Where do the 8 and 16 come from? Thanks : )
Answer 23 days ago
The second Sunday in any month must be from the 8th to the 14th. I believe the 16 should have been a 14.
23 days ago
There are a few mistakes. The second Sunday of a month has to fall on the 8th to the 14th. The first Sunday of any month must fall on the 1st to the 7th.
2 years ago on Introduction
Very helpful information!
MichaelB247, do you know how and where to add your code to existing one I use for Word Clock project. Thanks a lot!
Here is top part of code I use:
#include <Wire.h>
#include <RTClib.h>
#include <Adafruit_GFX.h>
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h>
#endif
//#include <DateTimeStrings.h>
#define RTCGND A2 // use this as DS1307 breakout ground
#define RTCPWR A3
RTC_DS3231 RTC; // Establish clock object
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(93, 6, NEO_GRB + NEO_KHZ800);
void setup() {
// Serial.begin(9600);
#if defined (__AVR_ATtiny85__)
if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
#endif
// set analog pins to power DS1307 breakout!
pinMode(RTCGND, OUTPUT); // analog 2
pinMode(RTCPWR, OUTPUT); // analog 3
digitalWrite(RTCGND, LOW); // GND for RTC
digitalWrite(RTCPWR, HIGH); // PWR for RTC
// put your setup code here, to run once:
pinMode(6, OUTPUT);
Wire.begin(); // Begin I2C
if (RTC.lostPower()) {
RTC.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
pixels.begin();
pixels.show();
// DateTime.sync(1262304000L);
}
void loop() {
DateTime theTime = RTC.now();
// Serial.print(theTime.hour(), DEC);
// Serial.print(':');
// Serial.print(theTime.minute(), DEC);
// Serial.print(':');
// Serial.print(theTime.second(), DEC);
// Serial.println();
// put your main code here, to run repeatedly:
for(int i = 0; i <93; i++){
pixels.setPixelColor(i, pixels.Color(0,0,0));
}
if(theTime.hour() == 0 || theTime.hour() == 12){
Reply 2 years ago
You should be able to add it in your main loop just after your call for RTC.now(). Hope this helps
Reply 2 years ago
Arduino: 1.8.5 (Mac OS X), Board: "Pro Trinket 5V/16MHz (USB)"
In file included from /Users/roman/Downloads/wc code/LEDClockTested/LEDClockTested.ino:50:0:
/Users/roman/Library/Arduino15/packages/arduino/hardware/avr/1.6.16/libraries/EEPROM/src/EEPROM.h: In function 'void loop()':
/Users/roman/Library/Arduino15/packages/arduino/hardware/avr/1.6.16/libraries/EEPROM/src/EEPROM.h:130:5: error: invalid declaration of member template in local class
template< typename T > T &get( int idx, T &t ){
^
/Users/roman/Library/Arduino15/packages/arduino/hardware/avr/1.6.16/libraries/EEPROM/src/EEPROM.h:137:5: error: invalid declaration of member template in local class
template< typename T > const T &put( int idx, const T &t ){
^
LEDClockTested:59: error: a function-definition is not allowed here before '{' token
{
^
LEDClockTested:474: error: expected '}' at end of input
}
^
Multiple libraries were found for "Wire.h"
Used: /Users/roman/Library/Arduino15/packages/adafruit/hardware/avr/1.4.9/libraries/Wire
Not used: /Users/roman/Library/Arduino15/packages/arduino/hardware/avr/1.6.16/libraries/Wire
exit status 1
a function-definition is not allowed here before '{' token
This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.
Reply 2 years ago
I am new to Arduino, this is error message I got afre I paste you code.
Any idea? Thanks Mishael!