From 5f7582ffdb9724a94a9a9adf088fbad358a5b31f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Fri, 30 Jan 2026 03:25:05 -0600 Subject: [PATCH] override localtime() to use our timezone By providing our own localtime() and localtime_r() implementations, user lambdas calling ::localtime() continue to work correctly without needing migration. This eliminates the breaking change while still achieving the memory savings. --- esphome/components/time/posix_tz.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/esphome/components/time/posix_tz.cpp b/esphome/components/time/posix_tz.cpp index 509643de4e5..bed1a3b6690 100644 --- a/esphome/components/time/posix_tz.cpp +++ b/esphome/components/time/posix_tz.cpp @@ -455,4 +455,24 @@ bool epoch_to_local_tm(time_t utc_epoch, const ParsedTimezone &tz, struct tm *ou } // namespace esphome::time +// Override libc's localtime functions to use our timezone +// This allows user lambdas calling ::localtime() to get correct local time +// without needing the TZ environment variable (which pulls in scanf bloat) + +// Thread-safe version +extern "C" struct tm *localtime_r(const time_t *timer, struct tm *result) { + if (timer == nullptr || result == nullptr) { + return nullptr; + } + esphome::time::epoch_to_local_tm(*timer, esphome::time::get_global_tz(), result); + return result; +} + +// Non-thread-safe version (uses static buffer, standard libc behavior) +extern "C" struct tm *localtime(const time_t *timer) { + // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) + static struct tm localtime_buf; + return localtime_r(timer, &localtime_buf); +} + #endif // USE_TIME_TIMEZONE