I am newbie from Belgium to this forum and wanted to share this piece of code I used for a few years to solve this issue on a particle core.
I didn’t find how to post code in a nice gray background so forgive me posting it as plain text.
//zomert is a bool, false when wintertime is active and true when summertime is active
switch (zomert) // check summer / winter time
{
case false: // if current setting is winter
if ( ((Time.day() >= (31-(((5*Time.year()/4)+4)%7))) and (Time.month() == 3 )) or ((Time.month() < 10) and (Time.month() > 3)) )
{
// summer time
zomert = true;
zoneUTC=2;
Time.zone(+2);
Particle.syncTime();
delay(2000);
}
break;
case true: // if current setting is summer
if ( ((Time.day() >= (31-(((5*Time.year()/4)+1)%7))) and (Time.month() == 10 )) or ((Time.month() < 3) or (Time.month() > 10)))
{
// winter time
zomert = false;
zoneUTC=1;
Time.zone(+1);
Particle.syncTime();
delay(2000);
}
break;
}
I have reformatted your code block.
To achieve the same thing you can use this icon or you use the edit option ( ) on your own post and see what I added before and after your code to achive the same thing (with the extra formatting hint cpp).
There are fully working and tested functions above in this topic thread which you could also use/study and that use the Time.isDST() and Time.beginDST() rather than move the Timezone!
What help are you after?
Hi Armor,
I will look at the functions above, i don’t have a specific problem, I just wanted to share my code that I’ve been using for a few years to tackle the daylight saving problem
Kind regards
The day of week numbering is quite convenient because the day - day of week will give you the previous Sunday.
What the author does is subtract 1 from "dayOfWeek" giving:
Sunday 0 .. Saturday 6.
instead of
Sunday 1 .. Saturday 7
I have not run anybody else's code to test but I have been using this routine below. It has been working for me. I hope it can illustrate a solution for you.
const int g_timeZone = -8; // Pacific Standard Time Zone from UTC
uint32_t g_timeNow = Time.now(); // save current Time snapshot
Time.zone(g_timeZone + (isDaylightSavingsTime() ? 1.0 : 0.0));
// set proper zone according to Standard or Daylight Savings regs
// Now, time is accurate for present day
// your code .....
bool isDaylightSavingsTime() { // Daylight Saving Time starts on the
// second Sunday in March of every year and ends on the first
// Sunday in November.
int dayNow = Time.day(g_timeNow);
int monthNow = Time.month(g_timeNow);
int dayOfWeekNow = Time.weekday(g_timeNow) - 1; // Sunday 0 .. Saturday 6
int previousSunday = dayNow - dayOfWeekNow;
switch (monthNow) {
case 1: // Jan, Feb and Dec are definitely standard time
case 2:
case 12:
return false;
case 4: // Apr to Oct are definitely DST
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
return true;
case 3: // March
if (previousSunday >= 8) { // today is 2nd Sunday or later
return true;
}
return false; // today is before 2nd Sunday
case 11: // November
if (previousSunday <= 0) { // today is before 1st Sunday
return true;
}
return false; // today is 1st Sunday or after
} // END switch
return false; // switch statement should have returned before now
} // END isDaylightSavingsTime
This works for me in the UK and currently all EU states.
// returns true or false should DST changed event be sent
// 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 or ends DST at UTC 02.00
bool isDSTactive()
{
float tz = Time.zone(); //offset from UTC
int dayOfMonth = Time.day();
int hour = ((Time.now() % 86400) / 3600);
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
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 > 0) //after the switching Sunday (dayOfWeek !=)
{
shouldDSTbeEnabled = (month == 3); //for March DST is true, for October not
}
else //switching Sunday (dayOfWeek = 0)
{
if (hour >= 1 && month == 3) shouldDSTbeEnabled = true; //time is 01:00 or later on switching sunday in march then DST should be ON
if (hour >= 2 && month == 10) shouldDSTbeEnabled = false; //time is 02:00 or later on switching sunday in october then DST should be OFF
}
break;
}
//then if a change condition check if switch required from current setting
if (shouldDSTbeEnabled && !Time.isDST()) //if it should be on but is off
{
Time.beginDST();
param.isDst = true;
putParameters();
return true;
}
else if (!shouldDSTbeEnabled && Time.isDST()) //if it should be off but is on
{
Time.endDST();
param.isDst = false;
putParameters();
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
huge thanks - and then what do you do in loop()? Do you just call it once a day or something? I’m aware that the above needs ‘activating’ or calling, right?
Thanks!
From loop() I typically call a clockTimeUpdate() function as below using a millis() based timer. I normally do this every 20 seconds to keep the clock time responsive and near to the internet time.
This is only suitable for the Photon which has a RTC, for the GEN3 devices I have implemented an external RTC (DS3231).
void clockTimeUpdate()
{
if (Time.isValid()) //only do this if RTC Time is valid
{
if (isDSTactive()) //true if changed, false if no change in DST - this is so it is only changed once
{
//publish event that DST has changed
}
//set clock time using formatted Time.now()
}
else
{
//if time is invalid then set clock time as not set
}
}
And that would just be something like Time.zone(-1); (for end of DST) or endDST() ? Do those essentially the same thing? Doesn't really matter which one I choose?
So it would be
void clockTimeUpdate()
{
if (Time.isValid()) //only do this if RTC Time is valid
{
if (isDSTactive()) //true if changed, false if no change in DST - this is so it is only changed once
{
beginDST();
}
//set clock time using formatted Time.now()
}
else
{
//if time is invalid then set clock time as not set
}
}
I guess I don't see how using the above code I would ever turn DST off?
Thanks. Sorry for being dumb about this, I'm just really hoping after years of fiddling and frustration to finally knock this on the head this year!
I think @robc has posted a complete example of the function plus code for loop to actually make the change but his example is for Pacific standard time so I can't just transplant his example for my GMT example
Actually scratch that. Surely if I just call your functionisDSTactive every day at 03:00 in the morning I will be laughing? This is what I meant by
but I think I wasn't clear enough!!
And I need to initially set a time.zone in setup, right?
EDIT Right, I've implemented some of this code, just wondering if there's a way to test it on the hoof to avoid waiting until March to see if it works? Could I Particle Publish a new month to see if it all works?
EDIT2 Ahh... first hang up, I think I must be going about this wrong. Trying to call isDSTactive from TimeAlarms and I can't because it's a bool not a void. Oops.
EDIT3 So close...I'm getting errors that "param" was not declared in this scope nor putParameters.
You can try using the statement Time.setTime() to make your test cases in your main loop. This will override the time set by the Particle Device Cloud. Print or publish your data after calling your DST calculating routine. Here are some examples:
// Set the time to 2014-10-11 13:37:42
Time.setTime(1413034662);
// Set the time to 2020-10-30 10:11:12
Time.setTime(1604052672); // Unix timestamp calculator
// Set the time to 2020-11-05 20:21:22
Time.setTime(1604607682); // Unix timestamp calculator
This does work and this is where DST is turned off in March!
In terms of testing - if you stay un connected from the Cloud you can set the time manually (beaten to the answer) - with the Photon the onboard RTC will be reset and the time valid.
isDSTactive() can be converted from bool to void type. I only have it that way because I need to know when DST has been set on or off to send an event to the web based device management app.