NTP, Daylight Saving Time switching problem.

I have NTP-based ESP8266 clock.
I would like to implement automatically DST switching twice a year.
Are there any ideas on how to implements this? Any libraries supporting this feature?
I am in New York City (time zone is -5Hours), but I would prefer universal solution, for various time zones.

See the example ESP8266 | NTP-TZ-DST

basically it's just a single line:

configTime(MYTZ, "pool.ntp.org");

doing all the magic including daylight saving.

If you don't mind to read from a non english page, you can use an even shorter version here:
ESP8266 NTP Abfrage mit Sommerzeit / Winterzeit (NodeMCU, Wemos D1) - but I guess copy/paste works anyway.
Or use this site in English for the ESP8266
http://werner.rothschopf.net/202011_arduino_esp8266_ntp_en.htm

for the ESP32
https://werner.rothschopf.net/microcontroller/202103_arduino_esp32_ntp_en.htm

replace the timezone according to this link
https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv

I have played a little with **ESP8266 ** --> NTP-TZ-DST example, cannot make it working....
I have set my wifi credentials and set MYTZ according to the link you shared (for New York):

#define MYTZ "EST5EDT,M3.2.0,M11.1.0"

No any other changes by me in example.
Seems like it is not working:

localtime: isdst=0 yday=316 wday=1 year=117 mon=10 mday=13 hour=12 min=15 sec=4
gmtime:    isdst=0 yday=316 wday=1 year=117 mon=10 mday=13 hour=17 min=15 sec=4
clock:     480s / 59082000ns
millis:    480059
micros:    480059103
gtod:      1510593304s / 998993us
time:      1510593304
timezone:  EST5EDT,M3.2.0,M11.1.0
ctime:     Mon Nov 13 12:15:04 2017
sntp0:     50.116.55.65 IPv6: No Reachability: 0

Have replaces NTP server with one I am using in my project ("us.pool.ntp.org") - still not working, output is the same...
What am I doing wrong?

"not working" ist somehow undefined.
describe - what do you get - what do you expect instead?

noiasca:
"not working" ist somehow undefined.
describe - what do you get - what do you expect instead?

I gave output... Will repeat it again. It is not changing time to correct one, see output:

localtime: isdst=0 yday=316 wday=1 year=117 mon=10 mday=13 hour=12 min=9 sec=4
gmtime:    isdst=0 yday=316 wday=1 year=117 mon=10 mday=13 hour=17 min=9 sec=4
clock:     120s / 59069000ns
millis:    120059
micros:    120059094
gtod:      1510592944s / 998960us
time:      1510592944
timezone:  EST5EDT,M3.2.0,M11.1.0
ctime:     Mon Nov 13 12:09:04 2017
sntp0:     50.116.55.65 IPv6: No Reachability: 0

Actually, I have found another NTP-TZ-DST example online, slightly different from what I have in my libraries folder, and seems like this example works. Strange, seems like there are two (at least) NTP-TZ-DST examples :slight_smile: around.
First one (not working one) marked as "NTP-TZ-DST (v2)" in comments, second, good one, does not have V2 mark...

Ok, thank you for directions, will investigate. Have never heard TZ may be specified such complex way as "EST5EDT,M3.2.0,M11.1.0", thought it is only numeric offset. Thank you again!

I did not get on how it actually works...
Below is NTP-TZ-DST sample, which seems to be working with auto-switching DST (for New York).
configTime() before is to use only numeric time zone offset (first and second parameters), now it accepts string like "EST5EDT,M3.2.0,M11.1.0". Where configTime() with such parameters is declared? I can only find this one:
void configTime(long gmtOffset_sec, int daylightOffset_sec, const char* server1, const char* server2, const char* server3), with numeric first and second parameters...
Below is whole source code...

/*
  NTP-TZ-DST
  NetWork Time Protocol - Time Zone - Daylight Saving Time

  This example shows how to read and set time,
  and how to use NTP (set NTP0_OR_LOCAL1 to 0 below)
  or an external RTC (set NTP0_OR_LOCAL1 to 1 below)

  TZ and DST below have to be manually set
  according to your local settings.

  This example code is in the public domain.
*/

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

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

#ifndef STASSID
#define STASSID "blablabla"
#define STAPSK  "kukuku"
#endif

#define SSID            STASSID
#define SSIDPWD         STAPSK
#define TZ              -5       // (utc+) TZ in hours, -5 for NY
#define DST_MN          60      // use 60mn for summer time in some countries

#define NTP0_OR_LOCAL1  0       // 0:use NTP  1:fake external RTC
#define RTC_TEST     1510592825 // 1510592825 = Monday 13 November 2017 17:07:05 UTC


//https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv
#define MYTZ "EST5EDT,M3.2.0,M11.1.0"  //automatically consider DST ???, see configTime(...)



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

#define TZ_MN           ((TZ)*60)
#define TZ_SEC          ((TZ)*3600)
#define DST_SEC         ((DST_MN)*60)

timeval cbtime;			// time set in callback
bool cbtime_set = false;

void time_is_set(void) {
  gettimeofday(&cbtime, NULL);
  cbtime_set = true;
  Serial.println("------------------ settimeofday() was called ------------------");
}

void setup() {
  Serial.begin(115200);
  settimeofday_cb(time_is_set);

#if NTP0_OR_LOCAL1
  // local

  ESP.eraseConfig();
  time_t rtc = RTC_TEST;
  timeval tv = { rtc, 0 };
  timezone tz = { TZ_MN + DST_MN, 0 };
  settimeofday(&tv, &tz);

#else // ntp

  //configTime(TZ_SEC, DST_SEC, "pool.ntp.org"); //not working, move it below.
  WiFi.mode(WIFI_STA);
  WiFi.begin(SSID, SSIDPWD);
  // don't wait, observe time changing when ntp timestamp is received //Wrong, needs to wait
  Serial.println("");
  while (WiFi.status() != WL_CONNECTED) 
    {
    delay(500);
    Serial.print(".");
    }

    //configTime(TZ_SEC, DST_SEC, "pool.ntp.org");
    configTime(MYTZ, "pool.ntp.org");
    
#endif // ntp
}

// for testing purpose:
extern "C" int clock_gettime(clockid_t unused, struct timespec *tp);

#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);
}

timeval tv;
timespec tp;
time_t now;
uint32_t now_ms, now_us;

void loop() {

  gettimeofday(&tv, nullptr);
  clock_gettime(0, &tp);
  now = time(nullptr);
  now_ms = millis();
  now_us = micros();

  // localtime / gmtime every second change
  static time_t lastv = 0;
  if (lastv != tv.tv_sec) {
    lastv = tv.tv_sec;
    Serial.println();
    printTm("localtime", localtime(&now));
    Serial.println();
    printTm("gmtime   ", gmtime(&now));
    Serial.println();
    Serial.println();
  }

  // time from boot
  Serial.print("clock:");
  Serial.print((uint32_t)tp.tv_sec);
  Serial.print("/");
  Serial.print((uint32_t)tp.tv_nsec);
  Serial.print("ns");

  // time from boot
  Serial.print(" millis:");
  Serial.print(now_ms);
  Serial.print(" micros:");
  Serial.print(now_us);

  // EPOCH+tz+dst
  Serial.print(" gtod:");
  Serial.print((uint32_t)tv.tv_sec);
  Serial.print("/");
  Serial.print((uint32_t)tv.tv_usec);
  Serial.print("us");

  // EPOCH+tz+dst
  Serial.print(" time:");
  Serial.print((uint32_t)now);

  // human readable
  Serial.print(" ctime:(UTC+");
  Serial.print((uint32_t)(TZ * 60 + DST_MN));
  Serial.print("mn)");
  Serial.print(ctime(&now));

  // simple drifting loop
  delay(10000);
}

I just used the

NTP-TZ-DST code

from the lib.

it is indicated in the sketch as NTP-TZ-DST (v2)

modified line 44 to
#define MYTZ "EST5EDT,M3.2.0,M11.1.0"

and currently I get the same time like google says what should be in New York:

localtime: isdst=0 yday=306 wday=1 year=120 mon=10 mday=2 hour=3 min=24 sec=19
gmtime:    isdst=0 yday=306 wday=1 year=120 mon=10 mday=2 hour=8 min=24 sec=19
clock:     4s / 216457000ns
millis:    4216
micros:    4216476
gtod:      1604305459s / 950169us
time:      1604305459
timezone:  EST5EDT,M3.2.0,M11.1.0
ctime:     Mon Nov  2 03:24:19 2020
sntp0:     pool.ntp.org (141.255.175.253) IPv6: No Reachability: 1

I'm on the actual ESP core 2.7.4 ... how old is yours?
Good morning by the way.

Actually, it is already good evening in our area :slight_smile:

Yes, I also have esp core 2.7.4.
It is strange, I have just verified again, time is not updated at all.
Even extra strange - I see some output differences comparing with yours, see below in bold.
Can you post here whole sketch? I will post mine either.
--- 8< ---
Starting...

Time is currently set by a constant:

localtime: isdst=0 yday=316 wday=1 year=117 mon=10 mday=13 hour=12 min=7 sec=5

gmtime: isdst=0 yday=316 wday=1 year=117 mon=10 mday=13 hour=17 min=7 sec=5
clock: 0s / 62939000ns
millis: 62
micros: 62961
gtod: 1510592825s / 2248us
time: 1510592825
timezone: EST5EDT,M3.2.0,M11.1.0
ctime: Mon Nov 13 12:07:05 2017

localtime: isdst=0 yday=316 wday=1 year=117 mon=10 mday=13 hour=12 min=8 sec=4
gmtime: isdst=0 yday=316 wday=1 year=117 mon=10 mday=13 hour=17 min=8 sec=4
clock: 60s / 60094000ns
millis: 60060
micros: 60060118
gtod: 1510592884s / 999390us
time: 1510592884
timezone: EST5EDT,M3.2.0,M11.1.0
ctime: Mon Nov 13 12:08:04 2017
sntp0: 50.116.55.65 IPv6: No Reachability: 0

localtime: isdst=0 yday=316 wday=1 year=117 mon=10 mday=13 hour=12 min=9 sec=4
gmtime: isdst=0 yday=316 wday=1 year=117 mon=10 mday=13 hour=17 min=9 sec=4
clock: 120s / 60078000ns
millis: 120060
micros: 120060103
gtod: 1510592944s / 999383us
time: 1510592944
timezone: EST5EDT,M3.2.0,M11.1.0
ctime: Mon Nov 13 12:09:04 2017
sntp0: 50.116.55.65 IPv6: No Reachability: 0
--- 8< ---

My source code is here: link (forum does not allow to insert it here, too many characters).
I have just removed wifi credentials.

I've just used the example with the TZ modififaction

/*
  NTP-TZ-DST (v2)
  NetWork Time Protocol - Time Zone - Daylight Saving Time

  This example shows:
  - how to read and set time
  - how to set timezone per country/city
  - how is local time automatically handled per official timezone definitions
  - how to change internal sntp start and update delay
  - how to use callbacks when time is updated

  This example code is in the public domain.
*/

//#include "credentials.h"
#ifndef STASSID
#define STASSID "your-ssid"
#define STAPSK  "your-password"
#endif

// initial time (possibly given by an external RTC)
#define RTC_UTC_TEST 1510592825 // 1510592825 = Monday 13 November 2017 17:07:05 UTC


// 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

// espressif headquarter TZ
//#define MYTZ TZ_Asia_Shanghai

// example for "Not Only Whole Hours" timezones:
// Kolkata/Calcutta is shifted by 30mn
//#define MYTZ TZ_Asia_Kolkata

// example of a timezone with a variable Daylight-Saving-Time:
// demo: watch automatic time adjustment on Summer/Winter change (DST)
//#define MYTZ TZ_Europe_London
#define MYTZ "EST5EDT,M3.2.0,M11.1.0"  // <-- changed to TZ New York

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

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

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

#include <sntp.h>                       // sntp_servermode_dhcp()

// for testing purpose:
extern "C" int clock_gettime(clockid_t unused, struct timespec *tp);

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

static timeval tv;
static timespec tp;
static time_t now;
static uint32_t now_ms, now_us;

static esp8266::polledTimeout::periodicMs showTimeNow(60000);
static int time_machine_days = 0; // 0 = now
static bool time_machine_running = false;

// OPTIONAL: change SNTP startup delay
// a weak function is already defined and returns 0 (RFC violation)
// it can be redefined:
//uint32_t sntp_startup_delay_MS_rfc_not_less_than_60000 ()
//{
//    //info_sntp_startup_delay_MS_rfc_not_less_than_60000_has_been_called = true;
//    return 60000; // 60s (or lwIP's original default: (random() % 5000))
//}

// OPTIONAL: change SNTP update delay
// a weak function is already defined and returns 1 hour
// it can be redefined:
//uint32_t sntp_update_delay_MS_rfc_not_less_than_15000 ()
//{
//    //info_sntp_update_delay_MS_rfc_not_less_than_15000_has_been_called = true;
//    return 15000; // 15s
//}

#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() {
  gettimeofday(&tv, nullptr);
  clock_gettime(0, &tp);
  now = time(nullptr);
  now_ms = millis();
  now_us = micros();

  Serial.println();
  printTm("localtime:", localtime(&now));
  Serial.println();
  printTm("gmtime:   ", gmtime(&now));
  Serial.println();

  // time from boot
  Serial.print("clock:     ");
  Serial.print((uint32_t)tp.tv_sec);
  Serial.print("s / ");
  Serial.print((uint32_t)tp.tv_nsec);
  Serial.println("ns");

  // time from boot
  Serial.print("millis:    ");
  Serial.println(now_ms);
  Serial.print("micros:    ");
  Serial.println(now_us);

  // EPOCH+tz+dst
  Serial.print("gtod:      ");
  Serial.print((uint32_t)tv.tv_sec);
  Serial.print("s / ");
  Serial.print((uint32_t)tv.tv_usec);
  Serial.println("us");

  // EPOCH+tz+dst
  Serial.print("time:      ");
  Serial.println((uint32_t)now);

  // timezone and demo in the future
  Serial.printf("timezone:  %s\n", getenv("TZ") ? : "(none)");

  // human readable
  Serial.print("ctime:     ");
  Serial.print(ctime(&now));

#if LWIP_VERSION_MAJOR > 1

  // LwIP v2 is able to list more details about the currently configured SNTP servers
  for (int i = 0; i < SNTP_MAX_SERVERS; i++) {
    IPAddress sntp = *sntp_getserver(i);
    const char* name = sntp_getservername(i);
    if (sntp.isSet()) {
      Serial.printf("sntp%d:     ", i);
      if (name) {
        Serial.printf("%s (%s) ", name, sntp.toString().c_str());
      } else {
        Serial.printf("%s ", sntp.toString().c_str());
      }
      Serial.printf("IPv6: %s Reachability: %o\n",
                    sntp.isV6() ? "Yes" : "No",
                    sntp_getreachability(i));
    }
  }
#endif

  Serial.println();
}

void time_is_set_scheduled() {
  // everything is allowed in this function

  if (time_machine_days == 0) {
    time_machine_running = !time_machine_running;
  }

  // time machine demo
  if (time_machine_running) {
    if (time_machine_days == 0)
      Serial.printf("---- settimeofday() has been called - possibly from SNTP\n"
                    "     (starting time machine demo to show libc's automatic DST handling)\n\n");
    now = time(nullptr);
    const tm* tm = localtime(&now);
    Serial.printf("future=%3ddays: DST=%s - ",
                  time_machine_days,
                  tm->tm_isdst ? "true " : "false");
    Serial.print(ctime(&now));
    gettimeofday(&tv, nullptr);
    constexpr int days = 30;
    time_machine_days += days;
    if (time_machine_days > 360) {
      tv.tv_sec -= (time_machine_days - days) * 60 * 60 * 24;
      time_machine_days = 0;
    } else {
      tv.tv_sec += days * 60 * 60 * 24;
    }
    settimeofday(&tv, nullptr);
  } else {
    showTime();
  }
}

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

  // setup RTC time
  // it will be used until NTP server will send us real current time
  time_t rtc = RTC_UTC_TEST;
  timeval tv = { rtc, 0 };
  settimeofday(&tv, nullptr);

  // 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);

  // NTP servers may be overriden by your DHCP server for a more local one
  // (see below)

  // ----> Here is the ONLY ONE LINE needed in your sketch

  configTime(MYTZ, "pool.ntp.org");

  //       Here is the ONLY ONE LINE needed in your sketch <----
  // pick a value from TZ.h (search for this file in your filesystem) for MYTZ

  // former configTime is still valid, here is the call for 7 hours to the west
  // with an enabled 30mn DST
  //configTime(7 * 3600, 3600 / 2, "pool.ntp.org");

  // OPTIONAL: disable obtaining SNTP servers from DHCP
  //sntp_servermode_dhcp(0); // 0: disable obtaining SNTP servers from DHCP (enabled by default)

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

  // don't wait for network, observe time changing
  // when NTP timestamp is received
  Serial.printf("Time is currently set by a constant:\n");
  showTime();
}

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

P.S.: if you come around to this thread - dont use sketch from this post. Go to NTP for the ESP8266 including day light saving Time (DST) without 3rd party library and use the proven sketch from my site.