Daylight savings problem


#1

I’m trying to build a simple oled display clock, it all seems to work with one small problem, daylight savings. I know that adding

Time.beginDST();

will add the hour necessary for BST but how do I get it to add the hour automatically?
Is there a function to do this, or is the only way to do it by manual method, ie checking the date and running

Time.endDST();

Forgive my ignorance but I’m not too clued up with coding!


#2

@peekay123 Has some code in his RGB Pong clock application that automatically sets DST.

You can dig through it here to pull out that part and reuse it. ;


#3

Thanks, but I’m having trouble getting my head around it. I’m in the UK so the rules are as follows
https://www.gov.uk/when-do-the-clocks-change
So far I’ve got this code but I’m not sure if it’s correct or not

bool IsDST(int dayOfMonth, int month, int dayOfWeek) {
// check for GMT/BST changeover
if (month < 3 || month > 10) {
    return false;
    }
if (month > 3 && month < 10) {
	return true;
	}
int previousSunday = dayOfMonth - (dayOfWeek - 1);

if (month == 3) {
	return previousSunday >= 25;
}
if (month == 10) {
	return previousSunday < 25;
}
return false;

}

If the truth be known, I don’t really understand how it works! Am I on the right track?


#4

Hi there, I have not dived into your code but this is what I came up with some time ago

bool isDST()
{ // (Central) European Summer Timer calculation (last Sunday in March/October)
  int dayOfMonth = Time.day();
  int month = Time.month();
  int dayOfWeek = Time.weekday() - 1; // make Sunday 0 .. Saturday 6

  if (month >= 4 && month <= 9)
  { // April to September definetly DST
    return true;
  }
  else if (month < 3 || month > 10)
  { // before March or after October is definetly standard time
    return false;
  }

  // March and October need deeper examination
  boolean lastSundayOrAfter = (dayOfMonth - dayOfWeek > 24);
  if (!lastSundayOrAfter)
  { // before switching Sunday
    return (month == 10); // October DST will be true, March not
  }

  if (dayOfWeek)
  { // AFTER the switching Sunday
    return (month == 3); // for March DST is true, for October not
  }

  int secSinceMidnightUTC = Time.now() % 86400;
  boolean dayStartedAs = (month == 10); // DST in October, in March not
  // on switching Sunday we need to consider the time
  if (secSinceMidnightUTC >= 1*3600)
  { // 1:00 UTC (=1:00 GMT/2:00 BST or 2:00 CET/3:00 CEST)
    return !dayStartedAs;
  }

  return dayStartedAs;
}

Simple Syslog client on a Photon
#5

@scruffr, Setting DST automatically has been on one of my to-do lists for a while. Now we are just about to implement DST in Europe I thought I would implement something to handle the European area market. The link here is a useful reference for all of the time zones and exact times DST starts and ends.

I thought I would post my attempt at this - have borrowed your algorithm! I am calling this function from a regularly called (20-30 seconds) routine which updates the displayed time.

// returns true or false should DST be enabled or disabled according to the time zone if (0.0(exc. Iceland), +1.0, +2.0) Europe exc. Russia/Belarus
// essentially from the last Sunday in March to the last Sunday in October DST is enabled at UTC 01.00 -> 02.00 and disabled at UTC 02.00 -> 01.00
// automatically begins DST at UTC 01.00 if should be enabled and is not and ends DST at UTC 02.00 if should be disabled and is enabled
bool isDSTactive()
{
    float tz = Time.zone();                                 //offset from UTC
    int dayOfMonth = Time.day();
    int hour = Time.hour();
    int month = Time.month();
    int dayOfWeek = Time.weekday() - 1;                     //make Sunday 0 .. Saturday 6
    bool shouldDSTbeEnabled = false;                        //not in European time zones for which coded DST rules apply by default

    Serial.printlnf("isDSTactive() tz %f dayofMonth %i dayOfWeek %i month %i hour %i", tz, dayOfMonth, dayOfWeek, month, hour);

    if (tz == 0.0 || tz == 1.0 || tz == 2.0)                //European time zones (WET/GMT, CET, EET)
    {
        switch (month)
        {
            case 1:                                         //Jan, Feb, Nov and Dec are definitely standard time
            case 2:
            case 11:
            case 12:
                shouldDSTbeEnabled = false;
                break;
            case 4:                                         //Apr to Sep definitely DST
            case 5:
            case 6:
            case 7:
            case 8:
            case 9:
                shouldDSTbeEnabled = true;
                break;
            case 10:                                        //March and October need deeper examination
            case 3:
                if (!(dayOfMonth - dayOfWeek > 24))         //but before switching Sunday     
                {
                    shouldDSTbeEnabled = (month == 10);     //for October DST will be true, for March not
                }
                else if (dayOfWeek)                         //after the switching Sunday (dayOfWeek != 0)
                {
                    shouldDSTbeEnabled = (month == 3);      //for March DST is true, for October not
                }
                break;
        }
        if (shouldDSTbeEnabled && !Time.isDST() && hour >= (1 + (int) tz))
        {
            Time.beginDST();                                //March last Sunday and after 01.00
        }
        else if (!shouldDSTbeEnabled && Time.isDST() && hour >= (2 + (int) tz))
        {
            Time.endDST();                                  //October last Sunday and after 02.00 (hour will include DST)
        }
    }
    return shouldDSTbeEnabled;
}

#6

If you want to support muiltiple European timezones, I’d recommend you go for the UTC hour and not the local since the switch always happens last sunday in March/October at 1:00 and 2:00 UTC irrespective of the time zone.

However there are also other timezones that feature 0.0, +1.0 or +2.0 offsets that won’t adhere to these switching rules (e.g. many African zones don’t switch at all).


#7

You are right there are other countries on these time zones and everyone has different rules. This is just for the European countries that use time zone 0.0, +1.0 and +2.0. I haven’t included +3.0 as Russia (Moscow) and Belarus are not on my list of markets. Iceland is UTC+0.0 and does not change.

Most of my devices are connected to a web app which can tell the device to enable or disable DST - this is the preferred approach whereby the DST country web site can be accessed to drive the changes.

I thought I was reading the local time hour (including DST and time zone) and then checking whether it was the same as UTC 01.00 to enable (if currently DST disabled) and UTC 02.00 to disable (if currently DST enabled)? Are you saying that there is a simpler method to check these 2 conditions?


#8

As you already know there are functions to preset the time offset for DST and to enable or disable that offset, and also check whether it is enabled or disabled.
None of these do the hard work to actually decide which is the right one to use, but they are handy to just switch on/off DST based on your own calculations.

What I was meaning with UTC hour ((Time.now() % 86400) / 3600) over local Time.hour() was that this way you’d just check for hour >= 1 and hour >= 2 instead of hour >= (1 + (int)tz) and hour >= (2 + (int)tz) respectively.


#9

Thanks - that is a cleaner way of making those tests.