Daylight saving time issue

Hi guys I have a function which adjusts hours depending if daylight saving is due or not.

Problem is that right on March 1-st daylight saving time starts to work in this function instead of kicking in on March 8.

At the time when I wrote this statements instead of using libraries was that I didn’t test it fully and and that time i.e. in December it behaved as it should so I didn’t bother with it.

Even now when Im going through it I cant find the problem. Little bit explanation, rtc time is being adjust not per UTC time but at Eastern time. That's why Im checking if month is within period of daylight saving time and if it is but _dst Boolean is not true then I`m making it true.

So now after initializing the time of rtc to eastern time I`m getting 1hr less. 09:00 is being converted to 08:00. Which should be done only on or after March 8.

Hope I explained the issue good enough.

if (((month == 3 && monthDay >= 14 - (1 + ((year + 2000) * 5 >> 2)) % 7) || (month > 3 && monthDay < 11) || (month == 11 && monthDay < 7 - (1 + (5 * (year + 2000) >> 2)) % 7)) && !_dst) ++hr;
  else EEPROM.put(EEPROM_DST, true);

  if (((month == 11 && monthDay >= 7 - (1 + (5 * (year + 2000) >> 2)) % 7) || (month > 11 && month < 3) || (month == 3 && monthDay < 14 - (1 + ((year + 2000) * 5 >> 2)) % 7)) && !_dst) --hr;
  else EEPROM.put(EEPROM_DST, false);

I can write the whole function if needed but the problem is in this 2 statements.

EDIT: year is 2 digit number from rtc the last 2 digits of the year that why its being added to 2000.

surepic:
I can write the whole function if needed

Please do. Just because you wrote something to the EEPROM doesn't mean it's being processed normally elsewhere. Also how can you know for sure that the variables in those 2 lines are not intialized properly? It's best if you post everything you have.

This

|| (month > 3 && monthDay < 11)

is going to cause DST to be recognized on the first day of March. What did you intend?

vaj4088:
This

|| (month > 3 && monthDay < 11)

is going to cause DST to be recognized on the first day of March. What did you intend?

Sorry this should be not monthDay<11 but month<11.

In the original function as usual I`m using letters which nobody likes :slight_smile: that’s why to post here I quickly made meaningful names.

Original was m>3 && m<11

Guess I solved it.

if (((month == 3 && monthDay >= 14 - (1 + ((year + 2000) * 5 >> 2)) % 7) || (month > 3 && month < 11) || (month == 11 && monthDay < 7 - (1 + (5 * (year + 2000) >> 2)) % 7)) && !_dst) {++hr;
  else EEPROM.put(EEPROM_DST, true);}

  if (((month == 11 && monthDay >= 7 - (1 + (5 * (year + 2000) >> 2)) % 7) || (month > 11 && month < 3) || (month == 3 && monthDay < 14 - (1 + ((year + 2000) * 5 >> 2)) % 7)) && !_dst) {--hr;
  EEPROM.put(EEPROM_DST, false);}

@aarg whole function as per request. I know variable name problems but I`m used to this style sorry :slight_smile:

void get_time(struct _time *my_time) {
#define DS1307_ADDRESS 0x68

  Wire.begin();
  
  #ifdef DS3232
  Wire.setClock(400000UL);
  #endif
  
  Wire.beginTransmission(DS1307_ADDRESS);

  Wire.write(byte(0));
  Wire.endTransmission();

  Wire.requestFrom(DS1307_ADDRESS, 7);

  itoa(bcdToDec(Wire.read()), my_time->_second, 10);
  prefix_shm(my_time->_second);

  itoa(bcdToDec(Wire.read()), my_time->_minute, 10);
  prefix_shm(my_time->_minute);

  unsigned char hr = bcdToDec(Wire.read());

  switch (current_zone) {

    case 1:
      !hr ? hr = 23 : --hr;
      break;

    case 2:
      !hr ? hr = 22 : (!(hr ^ 1) ? hr = 23 : hr -= 2);
      break;

    case 3:
      !hr ? hr = 23 : (!(hr ^ 1) ? hr = 22 : (!(hr ^ 2) ? hr = 23 : hr -= 3));
      break;

    case 4: case 5:
      !(hr ^ 23) ? hr = 0 : ++hr;
      break;

    default:
      break;
  }


  Wire.read(); //dow

  unsigned char md = bcdToDec(Wire.read());

  itoa(md, my_time->_monthDay, 10);

  unsigned char m = bcdToDec(Wire.read());

  unsigned char y = bcdToDec(Wire.read());

  if (((m == 3 && md >= 14 - (1 + ((y + 2000) * 5 >> 2)) % 7) || (m > 3 && m < 11) || (m == 11 && md < 7 - (1 + (5 * (y + 2000) >> 2)) % 7)) && !_dst) {
    EEPROM.put(EEPROM_DST, true);
    ++hr;
  }

  if (((m == 11 && md >= 7 - (1 + (5 * (y + 2000) >> 2)) % 7) || (m > 11 && m < 3) || (m == 3 && md < 14 - (1 + ((y + 2000) * 5 >> 2)) % 7)) && !_dst) {
    EEPROM.put(EEPROM_DST, false);
    --hr;
  }

  itoa(hr, my_time->_hour, 10);
  prefix_shm(my_time->_hour);

  itoa(y, my_time->_year, 10);

  const char *p[] = {"JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};

  strcpy(my_time->_month, p[--m]);

  return ;
}

You can use this library GitHub - JChristensen/Timezone: Arduino library to facilitate time zone conversions and automatic daylight saving (summer) time adjustments.

I know but size is too big compared to 2 statements? Did you find anything wrong with the statements? I hope i fixed it. But am open to any criticism.

To get around this problem I use a look up table in PROGMEM. I have 50 years worth of DST start and end dates. I highly doubt my Arduinos running in the real world will still be in use in 50 years.

guix:
You can use this library GitHub - JChristensen/Timezone: Arduino library to facilitate time zone conversions and automatic daylight saving (summer) time adjustments.

+1

Caseyryb lookup table is taking too much static memory vs simple equation that can calculate at runtime and then free it.

I was using Christensen library but again space issue.

surepic:
Caseyryb lookup table is taking too much static memory

PROGMEM does not use any more than a few bytes of static memory, just the access routines. I actually keep the timezones that I use with the Christensen library in PROGMEM, then move the one I'm using into a single timezone object.

Solved eventually by deleting second if statement and modifying procedure of setting clock in rtc depending if its set within daylight saving time period or no.