TimeLib.h not accounting for daylight savings

I have obtained the time via NTP with the correct daylight savings offset included.

  configTime(0, 0, ntpServerName);  // *** this sets up the clock to sync with your chosen NTP server/pool.
  Serial.println(F("Setting TZ env"));
  delay(500);
  setenv("TZ", "GMT0BST,M3.5.0/2,M10.5.0/2", 1);  // *** this is setup for UK daylight savings rules. You can look up your required TZ string online
  tzset();
  while (!time(nullptr))
  {
    Serial.println(F("Waiting for time.h"));
    delay(500);
  }
  Serial.println("Time Initialized");

…however when I then try to extract the hour using TimeLib.h functions, it appears to return the hour without the 1H offset included.

  time_t thisInstant;
  time(&thisInstant);
  Serial.print("Real Time:       "); Serial.println(ctime(&thisInstant));
  tmElements_t tm;
  breakTime(thisInstant, tm);
  Serial.print("Hour component:  "); Serial.println(tm.Hour);

Real Time: Thu Aug 21 16:29:49 2025

Hour component: 15

What gives ?

Since you know if it is DST or not from the NTP call, your code needs an if statement that tests the NTP DST and adjusts the Timelib function as appropriate.

Happy to do this, but does Time.h lib have a function to say if DST has been already applied or not ?

does Time.h lib have a function to say if DST has been applied or not ?

I don't think the ANSI/ISO standard time.h has anything like that... but sometimes the Arduino libraries are different.

Do a successful compile, now select the library TimeLib and right click, select Goto Definition. Do you see any DST functions?
Remember, DST is highly variable; you need Lat/Lon as well. There are numerous small towns, counties, and even an entire Canadian Province that do NOT use DST. I think there are also US states. I have no idea about the rest of the world.
We were supposed to get rid of this dumb idea several years ago but so far they can't seem to manage it.

There is a Timezone library that can handle the time zone conversions.

As long as I can remember the UK has been going to get rid of this dumb idea. I've no doubt that long after I'm gone the UK will be going to get rid of this dumb idea.

Where did you get TimeLib.h, I see Time.h only

Its probably that one, as TimeLib.h listed as Time, Michael Margolis

The Time library uses TimeLib.h, used to be Time.h but that caused confusion with the standard time.h library on file systems that are not case sensitive.

They won’t get rid of the idea because the people who make the decisions go surfing after coming home from the office.

Is there a particular reason for using TimeLib.h? I'm asking this because time.h seems to work just fine, like:

time_t t = time (NULL);

struct tm st;
return *localtime_r (&t, &st);

this works for CET/CEST with Arduino TimeLib (EDIT: now I see you are not using TimeLib)

  int m = month();
  if (m > 10 || m < 3) {
    setTime(now() - SECS_PER_HOUR);
  } else if (m == 3) {
    int d = 31 - ((((5 * year()) / 4) + 4) % 7);
    if (day() < d) {
      setTime(now() - SECS_PER_HOUR);
    }
  } else if (m == 10) {
    int d = 31 - ((((5 * year()) / 4) + 1) % 7);
    if (day() >= d) {
      setTime(now() - SECS_PER_HOUR);
    }
  }

Try the code on this page, it works for me:

Which board/processor are you coding for.

Is your location string correct? I can't find this string "GMT0BST,M3.5.0/2,M10.5.0/2" on the usual site.
Leo..

This works for me, with your location string , on an ESP32C3.
I included a callback to wait for the NTP update.
It only needs WiFi credentials.
Leo..

#include <WiFi.h>  // ESP32
#include "esp_sntp.h" // for callback
unsigned long prevTime;
bool reSync;
time_t now;  // holds epoch
tm tm;       // time struct
char timeStr[9];

void cbSyncTime(struct timeval *tv) {  // sync callback
  reSync = true;
  Serial.println("Time was updated"); // prints every three hours
}

void setup() {
  Serial.begin(115200);
  WiFi.begin("SSID", "PASS"); // WiFi credentials
  sntp_set_time_sync_notification_cb(cbSyncTime); // enable callback
  configTzTime("GMT0BST,M3.5.0/2,M10.5.0/2", "pool.ntp.org");
  while (!reSync) yield(); // wait here for a valid time string
}

void loop() {
  time(&now);
  if (now != prevTime) {     // if time has changed
    prevTime = now;          // remember
    localtime_r(&now, &tm);  // convert epoch to local time
    printf("%02u:%02u:%02u\n", tm.tm_hour, tm.tm_min, tm.tm_sec);
    Serial.print("Hour component:  ");
    Serial.println(tm.tm_hour);
  }
}
int m = month();
  if (m > 10 || m < 3) {
    setTime(now() - SECS_PER_HOUR);
  } else if (m == 3) {
    int d = 31 - ((((5 * year()) / 4) + 4) % 7);
    if (day() < d) {
      setTime(now() - SECS_PER_HOUR);
    }
  } else if (m == 10) {
    int d = 31 - ((((5 * year()) / 4) + 1) % 7);
    if (day() >= d) {
      setTime(now() - SECS_PER_HOUR);
    }
  }

Sorry, but what has that got to do with Time Zones and Daylight Saving Time?

+1
Time libraries with DST calculations are now included in ESP board files.
No extra libraries or code needed.
Just enter the correct location string, found on this site.

This is the only line needed for TZ and DST.
configTzTime("GMT0BST,M3.5.0/1,M10.5.0", "uk.pool.ntp.org"); // London
Leo..

However, that requires an internet connection. I know if it's an ESP32 then the internet is sort of needed but, some newbs may not grok the details.

This is the absolute minimum needed for an ESP32 to get internet time.
Unlike the sketch in post#16, it does not wait for a valid timestring on startup.
Leo..

#include <WiFi.h>  // ESP32
unsigned long prevTime;
time_t now;  // holds epoch
tm tm;       // time struct

void setup() {
  Serial.begin(115200);
  WiFi.begin("SSID", "PASS"); // WiFi credentials
  configTzTime("GMT0BST,M3.5.0/1,M10.5.0", "uk.pool.ntp.org");  // London
}

void loop() {
  time(&now);
  if (now != prevTime) {     // if time (in seconds) has changed
    prevTime = now;          // remember
    localtime_r(&now, &tm);  // convert epoch to local time
    printf("%02u:%02u:%02u\n", tm.tm_hour, tm.tm_min, tm.tm_sec);
  }
}

Edit: more time elements are available to print, like year, day, date, month summer/winter, etc.