ESP8266 NTP-TZ-DST example simplified

This isn't a question, just thought it might be handy for other less advanced users if I share what I've managed to figure out with regards to the ESP8266 NTP-TZ-DST example, which is the example code to show how the ESP8266 can get the current time in your time zone and handle daylight saving time for your location.

I found the example to do a great job demonstrating what the core code can do, but it does it in a way that's not very accessible for people who aren't already experts: the syntax seems to be quite avanced in places, and some key chunks of code have no comments or explanations as to what they do. For me this made it hard to know what was what, and what I needed to achieve my goals for my project.

What I looked for and didn't find was an explanation of the code. What I've figured out is far from a complete explanation of the code, but it seems to work, and seems to be the minimum I can get away with. I welcome constructive contributions to fill in the gaps in the comments. I will endeavour to come back here periodically to incorporate new information, if there is any.

So, here is my simplified example of the NTP-TZ-DST code, with additional comments (so far as I'm able to figure it out!). This code just gets the time and then prints a couple of pieces of data to the serial port as examples. It allows you to easily set the time zone and adjusts for DST, though you'll need to use the full example to see that demonstrated.

/*
  NTP-TZ-DST_simplified (v0)
  NetWork Time Protocol - Time Zone - Daylight Saving Time

  This is a greatly simplified version of NTP-TZ-DST (v2) intended to be easier to understand with just the basic functions

  This example shows:
  - how to read time
  - how to set timezone per country/city
  - how to use callbacks when time is updated

  This example code is in the public domain.
*/


#ifndef STASSID
#define STASSID "yourSSID"
#define STAPSK  "yourPASSWORD"
#endif

// This database is autogenerated from IANA timezone database
//    https://www.iana.org/time-zones
// and can be updated on demand in this repository
#include <TZ.h>

// "TZ_" macros follow DST change across seasons without source code change
// check for your nearest city in TZ.h
#define MYTZ TZ_Pacific_Auckland

////////////////////////////////////////////////////////

#include <ESP8266WiFi.h>
#include <coredecls.h>                  // settimeofday_cb()
#include <PolledTimeout.h>

#include <time.h>                       // time() ctime()
#include <sys/time.h>                   // struct timeval

// this line is necessary, not sure what it does
extern "C" int clock_gettime(clockid_t unused, struct timespec *tp);

// An object which can store a time
static time_t now;

// this uses the PolledTimeout library to allow an action to be performed every 20 seconds
static esp8266::polledTimeout::periodicMs showTimeNow(20000);

/* This is a shortcut to print a bunch of stuff to the serial port.  It's very confusing, but shows what values are available
#define PTM(w) \
  Serial.print(" " #w "="); \
  Serial.print(tm->tm_##w);

void printTm(const char* what, const tm* tm) {
  Serial.print(what);
  PTM(isdst); PTM(yday); PTM(wday);
  PTM(year);  PTM(mon);  PTM(mday);
  PTM(hour);  PTM(min);  PTM(sec);
}
*/

void showTime() {   // This function is used to print stuff to the serial port, it's not mandatory
  now = time(nullptr);      // Updates the 'now' variable to the current time value

  // human readable
  Serial.print("ctime:     ");
  Serial.print(ctime(&now));
  // Here is one example showing how you can get the current month
  Serial.print("current month: ");
  Serial.println(localtime(&now)->tm_mon);
  // Here is another example showing how you can get the current year
  Serial.print("current year: ");
  Serial.println(localtime(&now)->tm_year);
  // Look in the printTM method to see other data that is available
  Serial.println();
}

void time_is_set_scheduled() {    // This function is set as the callback when time data is retrieved
  // In this case we will print the new time to serial port, so the user can see it change (from 1970)
  showTime();
}

void setup() {
  Serial.begin(115200);
  Serial.println("\nStarting...\n");

  // install callback - called when settimeofday is called (by SNTP or us)
  // once enabled (by DHCP), SNTP is updated every hour
  settimeofday_cb(time_is_set_scheduled);

  // This is where your time zone is set
  configTime(MYTZ, "pool.ntp.org");

  // start network
  WiFi.persistent(false);
  WiFi.mode(WIFI_STA);
  WiFi.begin(STASSID, STAPSK);

  // On boot up the time value will be 0 UTC, which is 1970.  
  // This is just showing you that, so you can see it change when the current data is received
  Serial.printf("Time is currently set by a constant:\n");
  showTime();
}

void loop() {
  if (showTimeNow) {
    showTime();
  }
}

*Note: you need to put in your wifi SSID and password so it can get an internet connection. You may also want to change your timezone, (find your timezone here: Arduino/TZ.h at master · esp8266/Arduino · GitHub) which is on the line

// "TZ_" macros follow DST change across seasons without source code change
// check for your nearest city in TZ.h
#define MYTZ TZ_Pacific_Auckland
1 Like

I tried the code and got the below output. Is that what is expected?

ctime:     Thu Jan  1 21:01:00 1970
current month: 0
current year: 70

ctime:     Thu Jan  1 21:01:20 1970
current month: 0
current year: 70

ctime:     Thu Jan  1 21:01:40 1970
current month: 0
current year: 70

ctime:     Thu Jan  1 21:02:00 1970
current month: 0
current year: 70

If you don't put in your wifi SSID and password, then yes!

I've edited the original post to make this clearer, thanks for highlighting this gap.

"If you don't put in your wifi SSID and password, then yes!"

I did have the proper SSID and password in my first test of the code. I used the same SSID and password in the latest code revision, and got the below, which is more reasonable. I suspect the change in my results are not based on the SSID and password, but maybe something else.

ctime:     Wed Jan 22 08:27:50 2020
current month: 0
current year: 120

ctime:     Wed Jan 22 08:28:10 2020
current month: 0
current year: 120

ctime:     Wed Jan 22 08:28:30 2020
current month: 0
current year: 120

zoomkat:
"If you don't put in your wifi SSID and password, then yes!"

I did have the proper SSID and password in my first test of the code. I used the same SSID and password in the latest code revision, and got the below, which is more reasonable. I suspect the change in my results are not based on the SSID and password, but maybe something else.

Hmm, I didn't make any changes to the code, just the instructions. Oh well, at least it's working now :slight_smile: