Library for time zone conversions and automatic DST adjustments

Header

/*----------------------------------------------------------------------*
 * Arduino Timezone Library v1.0                                        *
 * Jack Christensen Mar 2012                                            *
 * Mitch Feig added setRule method so rules can be updated 6/16                                                                    *
 * This work is licensed under the Creative Commons Attribution-        *
 * ShareAlike 3.0 Unported License. To view a copy of this license,     *
 * visit http://creativecommons.org/licenses/by-sa/3.0/ or send a       *
 * letter to Creative Commons, 171 Second Street, Suite 300,            *
 * San Francisco, California, 94105, USA.                               *
 *----------------------------------------------------------------------*/ 
 
#ifndef TimeZone_h
#define TimeZone_h
#include <Arduino.h> 
#include <TimeLib.h>              

//structure to describe rules for when daylight/summer time begins,
//or when standard time begins.
struct TimeChangeRule
{
    char abbrev[6];    //five chars max
    uint8_t week;      //First, Second, Third, Fourth, or Last week of the month
    uint8_t dow;       //day of week, 1=Sun, 2=Mon, ... 7=Sat
    uint8_t month;     //1=Jan, 2=Feb, ... 12=Dec
    uint8_t hour;      //0-23
    int offset;        //offset from UTC in minutes
};
        
class TimeZone
{
    public:
     TimeZone();
 void setRule(TimeChangeRule dstStart, TimeChangeRule stdStart);
        time_t toLocal(time_t utc);
        time_t toUTC(time_t local);
        boolean utcIsDST(time_t utc);
        boolean locIsDST(time_t local);
    private:
        void calcTimeChanges(int yr);
        time_t toTime_t(TimeChangeRule r, int yr);
       TimeChangeRule _dst;    //rule for start of dst or summer time for any year
       TimeChangeRule _std;    //rule for start of standard time for any year
TimeChangeRule _dstSave;
TimeChangeRule _stdSave;
       time_t _dstUTC;         //dst start for given/current year, given in UTC
        time_t _stdUTC;         //std time start for given/current year, given in UTC
        time_t _dstLoc;         //dst start for given/current year, given in local time
        time_t _stdLoc;         //std time start for given/current year, given in local time
};
#endif

Your library version posted is different than the github version I have been using.
After several edits of the library.

// at end of setup()
myDST.setRule( myDT , myST );

IT WORKS !!!

I removed some code that wasn't related before I posted, and I probably should have tested first. Sorry! Please post the updated programs.

If anyone can suggest a better way to do this, please do so. At some point this functionality should get to Github once it is looked over by someone who knows more about OOP. The ability to change rules programaically is useful.

Mitch, I have been programming in OOP for over 30 years.

When I posted, I did not have time then to track down the variables and types to find what to manipulate.

Last night I finally had some time to really look over the library code and it looks really good. I think its ready for github posting.

I should note the library works fine on the ESP8266 and ESP32 as well.

My clock code is Atomic(NTP) with WiFi on the ESP8266 with web setup. I plan a Fibonacci version soon. Either one i would offer as an example to add to the library if you like.

I did re-sequence some of the timezone.h file. For some reason on the ESP32, if setRule() is after toLocal() it had a hiccup. (Still not sure why) Send me an email if you want the full code. Mi ck ey AT Dat as oft LLC DOT co m (caps not needed)

class Timezone
{
public:
Timezone(TimeChangeRule dstStart, TimeChangeRule stdStart);
Timezone(int address);
void setRule(TimeChangeRule dstStart, TimeChangeRule stdStart);
time_t toLocal(time_t utc);
time_t toLocal(time_t utc, TimeChangeRule **tcr);
time_t toUTC(time_t local);
bool utcIsDST(time_t utc);
bool locIsDST(time_t local);
void readRules(int address);
void writeRules(int address);

private:
void calcTimeChanges(int yr);
time_t toTime_t(TimeChangeRule r, int yr);
TimeChangeRule _dst; //rule for start of dst or summer time for any year
TimeChangeRule _std; //rule for start of standard time for any year
TimeChangeRule _dstSave;
TimeChangeRule _stdSave;
time_t _dstUTC; //dst start for given/current year, given in UTC
time_t _stdUTC; //std time start for given/current year, given in UTC
time_t _dstLoc; //dst start for given/current year, given in local time
time_t _stdLoc; //std time start for given/current year, given in local time
};
#endif

Great work, Mickey. Please branch and upload to Github.

Next, I'd like to see it work with WiFi101 and the MKR1000. I don't think Time.cpp is used. When I have time I'll look into it.

Mitch

WiFi101 is just a WiFi shield for Arduino and will run time.h just fine
MKR1000 a Cortex-M0 MCU, this i have used time.h on this core

Time.h will run on almost any Atmel chip and most other processors. I have even used time.h on the attiny13 and thats not much memory.

i should note i have used time.h on ST Cortex-M0, 80C52, several Atmel, ESP8266, ESP32 and TI 430 processors with good results. only the 80C52 needed a special #ifdef to compile

i expect your library should run on all of these since it is really just an interface to the time.h in the first place.

The ONLY chip specific code I see are the EEPROM read/write functions and fortunately you already have the #ifdefs in place to deal with this.

only the "#include <WProgram.h> " is questionable for other IDEs than Arduino since WProgram.h is part of Arduino. "else if ARDUINO < 100" will catch lesser Arduino versions and remove the Arduino headers in NON-Arduino IDEs.

Something like this should remove the Arduino headers if used outside of the Arduino IDE.

   #if ARDUINO >= 100
   #include <Arduino.h> 
   #else if ARDUINO < 100
   #include <WProgram.h> 
   #endif

Excellent work.

This one looks like a combination of Fabrice Weinberg's NTPClient, and the Timzone library by Jack Christensen:

It's devoid of examples, but it's on my list to try because it puts both NTP time, and timezone calculations, in one place.

EDIT: It doesn't appear to work. Here's what I used to test:

#include <WiFi.h>
#include <TimeLib.h>
#include <NTPClientTZ.h>
#include <SPI.h>



// initialize and instantiate tz object
//TimeChangeRule dSt; // = {};
//TimeChangeRule sTd; // = {};
//Timezone1 tz(dSt, sTd);

const char *ssid     = "SSID";
const char *password = "Password";

TimeChangeRule dSt = {"DST", 2, 1, 3, 2, 0}; // March, 2nd Sunday, 2:00am
TimeChangeRule sTd = {"STD", 1, 1, 11, 2, 0}; // November, 1st Sunday, 2:00am

// You can specify the time server pool and the offset, (in seconds)
// additionaly you can specify the update interval (in milliseconds).
NTPClientTZ timeClient("us.pool.ntp.org", 3600, 60000, dSt, sTd);

void setup() {
  Serial.begin(115200);
  delay(500);

  WiFi.begin(ssid, password);

  while ( WiFi.status() != WL_CONNECTED ) {
    delay ( 500 );
    Serial.print ( "." );
  }
//changeRule();
}

void loop() {
  timeClient.update();

  Serial.println(timeClient.getFormattedTime());

  delay(1000);
}
void changeRule() {
// rule, week of month, day of week, month, hour, offset
TimeChangeRule dSt = {"DST", 2, 1, 3, 2, 0}; // March, 2nd Sunday, 2:00am
TimeChangeRule sTd = {"STD", 1, 1, 11, 2, 0}; // November, 1st Sunday, 2:00am
timeClient.setRule(dSt, sTd); // set rules
}

HELLO!
I have some questions about this library and RTC library of arduino IDE.

so i work in a project in which i use the ds1307 module and i want to use both libraries, can i do that with out any problem?

An other question is; if i write the code for the ds1307 could i replace the ds1307 with ds3231 without changes in the code?

Thank you in advance.

You can use Time, TimeZone, and one of the RTC libraries together. In fact, TimeZone is dependent on Time.

I believe the DS1307 library will work with the DS3231.

Brilliant library
I've been sweating blood trying to get the daylight saving rules to work in Excel prior to transferring to code and getting nowhere fast.
I have an energy monitoring programme that counts the meter (gas, electricity etc.) pulses that puts the RTC (GMT) time/date-stamp on it and for clarity needed the local time/date as well.
Saved me a lot of midnight oil, especially galling as I just found I installed the library last year.
I will get the Excel version going for personal satisfaction, but the rules to compare the system date/time against the changeover date/time are a lot harder than they appear.
Personally speaking, I'm in favour of leaving the damn clocks alone, as "putting the clocks back" in October just brings the gloom on one hour earlier.

Agreed. I hate DST. Imagine writing DST rules for Israel, where they take religious holidays into account, too!

tigger:
Brilliant library
I've been sweating blood trying to get the daylight saving rules to work in Excel prior to transferring to code and getting nowhere fast.
I have an energy monitoring programme that counts the meter (gas, electricity etc.) pulses that puts the RTC (GMT) time/date-stamp on it and for clarity needed the local time/date as well.
Saved me a lot of midnight oil, especially galling as I just found I installed the library last year.
I will get the Excel version going for personal satisfaction, but the rules to compare the system date/time against the changeover date/time are a lot harder than they appear.
Personally speaking, I'm in favour of leaving the damn clocks alone, as "putting the clocks back" in October just brings the gloom on one hour earlier.

Here is one method, which probably would not be too hard to make work in Excel:
https://forum.arduino.cc/index.php?topic=370460.msg2554547#msg2554547