Dealing With Daylight Saving Time on DS3231

Why so rude? This is entirely volunteering; no one is required to help you - but some do, and you should be thankful to those people.

Many Arduino sketches spend most of the time doing nothing anyway. Never heard one complain.

Aesthetics do matter, here just take the win. Pick from any of the offered solutions the one that offends least.

Since we've opened it for voting, I prefer @anon57585045's solution in #7. :expressionless:

a7

The timezone library works very well.

It does, but I discovered that it has dependencies on the AVR implementation, won't compile on all Arduinos.

To wrap up, from my perspective.

I'm immensly grateful to David 2018 for the suggestion to store current state of the clock in EEPROM. It's the key to a simple solution.

I'll put a flag there for whether we're (already) in DST or not. Then at any date/time in the DST "window" I'll check the value of that flag, increment or decrement the RTC by an hour when necessary and re-set the EEPROM flag to indicate the new state. Simples, as a merekat might say.

I need to resond to Ard_Flamingo's question also. My old gran taught me to never be the first to be rude but to never to suck it up and whenever possible to respond in kind. I live in a country where no-one has a gun, so it's usually good advice.

I can only suggest re-reading the thread from the start, especially the question and the polite re-statement for clarity. People come here for advice, not to be patronised or spoken down to. And just to be clear - post #7 doesn't get close to answering the query. TimeSpan was offered, I asked about it, got no reply.

But thanks again David.

Peace out.

See post #20

Or just add 3600 seconds to the Epoch Time.

2 Likes

............ Tried it, it doesn't work. Maybe it's good with a different library, just not the one I quoted in the original question.

All done. I have a solution working, tested and incorporated into a bigger sketch.

The attached is the Daylight Saving Time sketch, which can be run as a function if required.

It could be (and indeed, is in my final implementation) much, much smaller but it makes my snot fizz trying to understand other peoples' logic and code saving trickery.

So I offer it in all of it's fully commented, clunky glory and hope it's of use to someone.

/*********************************************************************************
OldCodger's Sketch to update RealTimeClock to reflect daylight saving time (DST)
Works equally well with DS3231 (as here) and DS1307

Run the loop part as a function if required. 
The only variable needed to pass & return to a function is DSTstate. 

Uses EEPROM to store value of whether DST has been set, this keeps things non-volatile.
The sketch is designed to ensure there are only writes to (and reads from) 
EEPROM twice a year to avoid excessive access causing memory damage. 

Day of week runs from 0 (Sunday) to 6 (Saurday). 
Clock changes according to UK/EU DST rules at 2am on last Sunday in month.

If uploading for 1st time, you may need to set byte for DSTstate in EEPROM
separately beforehand, but you can do this via serial monitor when neccessary.
Or, make a small mod to whatever sketch you use to set the time initially.
Use the table below to decide what value to set the byte at address 0.  
************************************************************************************/

/***********************************************************************************
  DSTstate byte values at address == 0 are set as follows:
    0   =   DST not set, no action required, wait for last Sunday in March
    1   =   DST is set, no action required, wait for last Sunday in October
    2   =   DST not set but increment hour ++ and set EEPROM byte to 1
    3   =   DST is set, but decrement hour -- and set EEPROM byte to 0

  **********************************************************************************/

// ---------  LIBRARIES  ----------
#include "RTClib.h"              // for DS3231 Real Time Clock               
#include <EEPROM.h>             // to permit save DST state to EEPROM            

RTC_DS3231 rtc;               // Identifies the clock
// ---------  CONSTANTS  ----------

const byte address  = 0;   // Sets an EEPROM address to write & read the value of DSTstate

// ---------  VARIABLES  ----------

byte  DSTstate  = 0;    // Indicates whether DST has been set on or off, saved in EEPROM
byte  hrNew     = 3;   //  Just a dummy value here, to avoid clock overflow if we get things wrong

int  yyyy;           //  year, 4 digit, so needs to be an integer
byte mm;            //  month
byte dd;           //  day
byte weekDay;     //  day of week (Sunday = 0)
byte hr;         //  hour
byte min;       //  minutes
byte sec;      //  seconds

void setup() 
{
   
DSTstate = EEPROM.read(address);      // Get current DSTstate to use in if statements
  if (DSTstate > 3) {DSTstate = 0;}  // If using a new Arduino with ths sketch, set to 0

 }

void loop() 
{
   DateTime now = rtc.now();    // Get the date/time now from RTC

  yyyy     = now.year();        
  mm       = now.month();
  dd       = now.day();
  weekDay  = now.dayOfTheWeek();
  hr       = now.hour();
  min      = now.minute();
  sec      = now.second();

// So....... now we look at DST state and make changes as necessary if we are in the date window 

/************ The next two if statements can be removed or commented out ******* 
************* They are only included so that we can change the clock     *******
************* outside the usual March and Octobr windows                 ******/
if (DSTstate == 3)
{
  hrNew = hr-1;
  rtc.adjust(DateTime(yyyy, mm, dd, hrNew, min, sec));   // update RTC with new time
  DSTstate  = 0;
  EEPROM.write(address, DSTstate);
  }

if (DSTstate == 2)
{
  hrNew = hr+1;
  rtc.adjust(DateTime(yyyy, mm, dd, hrNew, min, sec));   // update RTC with new time
  DSTstate  = 1;
  EEPROM.write(address, DSTstate);
  }
// ********* End of the if statements that could be removed ****************
// ********* Important part of the sketch begins here       ****************

 if (DSTstate == 1 && mm == 10 && weekDay == 0 && dd >= 25 && hr == 2)  // are we in October window?
  {
  hrNew = hr-1;
  rtc.adjust(DateTime(yyyy, mm, dd, hrNew, min, sec));                // update RTC with new time
  DSTstate  = 0;
  EEPROM.write(address, DSTstate);
  }

 if (DSTstate == 0 && mm == 3 && weekDay == 0 && dd >= 25 && hr == 2)  // are we in March window?
  {
  hrNew = hr+1;
  rtc.adjust(DateTime(yyyy, mm, dd, hrNew, min, sec));               // update RTC with new time
  DSTstate  = 1;
  EEPROM.write(address, DSTstate);
  }

}

I haven't studied your code, but in case it makes any difference, the datasheet says the permitted values for day of the week are 1 through 7.

I've made a number of clocks, time switches etc., incorporating a DS3231 and similar modules. My approach is NOT to update the RTC with daylight saving time but to run it in UTC. This is often more natural because it correponds with the time source (ntp, gps etc.) . For displaying the correct (local) time, I use a time zone library together with a time library to calculate the current local time offset. The exact details depend on the platform.

Try this simplified code which serial prints the clock info. It outputs a Sunday as day zero and if you set it to today (Saturday 1/4/2023) it outputs a Saturday as day 6.

I did start with 1-7 and couldn't understand why the sketch wouldn't work. It took me ages to figure out. I couldn't find anything clear in the library documentation so had to experiment a bit.

/****************************************************************************
Real Time Clock based on DS3231 RTC chip.  
*****************************************************************************/
#include "RTClib.h"
#include <Wire.h>
RTC_DS3231 rtc;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

void setup () {
 
Serial.begin(19200);
  if (! rtc.begin()) {while (1) delay(10); }
 
 rtc.adjust(DateTime(2023, 4, 2, 12, 0, 0));    // comment this out to set time/date as compile date/time
// rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));   //  un-comment this out to set time/date as compile date/time
 }

void loop () {
    DateTime now = rtc.now();
Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
Serial.println();
   Serial.print("Date: ");
    Serial.print(now.day());
    Serial.print('/');
    Serial.print(now.month());
    Serial.print('/');
    Serial.print(now.year());
   
Serial.println();

    Serial.print("Day of week ");
    Serial.print(now.dayOfTheWeek());
    Serial.println();
    Serial.println("******************************");
      
Serial.println();

    delay(3000);
}

Each to his own I suppose.

My application doesn't have any connection to a time source but does read the RTC on every loop and log some data to a local server over ethernet. So it's cleaner for me to change the clock than have to add an hour to get the local time.

Your approach is fine, but we would need to juggle a bit around midnight every day to not only change the hour but also the date and weekday. I wanted to avoid that hassle of using another library. Plus, I don't keep my watch on UTC and mentally add an hour every time I look at it so adjusting the clock is more natural for me.

From RTClib.cpp

547 /**************************************************************************/
548 /*!
549     @brief  Return the day of the week.
550     @return Day of week as an integer from 0 (Sunday) to 6 (Saturday).
551 */
552 /**************************************************************************/
553 uint8_t DateTime::dayOfTheWeek() const {

Yeah, it's a bit wierd. The library RTClib.h actually says:

/*!
      @brief  Convert the day of the week to a representation suitable for
              storing in the DS3231: from 1 (Monday) to 7 (Sunday).
      @param  d Day of the week as represented by the library:
              from 0 (Sunday) to 6 (Saturday).
      @return the converted value
  */

........so I can see how people (including me) get confused.
All I can say is - it works as per the way I coded it in the sketch. Sunday is day 0.

Ok, so your library converts DOY from 0-6 to 1-7 for the RTC. That's fine. And I assume it makes the same conversion for alarm1 and alarm2 settings.

On my HP calculator, Sunday is 7, Monday is 1. So I guess it's just what the library author thought was most intuitive.

Wow. I thought I was showing my age by still wearing a watch. But you still use a calculator? Respect!

Not just a calculator, but an RPN calculator. None of that "equals" key rubbish.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.