From 5861cf37f96628810e59526deeb8f386c66a391e Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 25 Oct 2025 11:20:06 -0700 Subject: [PATCH] [core] Simplify ESPTime::strftime() and save 20 bytes flash --- esphome/core/time.cpp | 22 ++++++++-------------- esphome/core/time.h | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/esphome/core/time.cpp b/esphome/core/time.cpp index 1285ec6448..9a1a0dc492 100644 --- a/esphome/core/time.cpp +++ b/esphome/core/time.cpp @@ -46,24 +46,18 @@ struct tm ESPTime::to_c_tm() { return c_tm; } -std::string ESPTime::strftime(const std::string &format) { - std::string timestr; - timestr.resize(format.size() * 4); +std::string ESPTime::strftime(const char *format, size_t format_len) { struct tm c_tm = this->to_c_tm(); - size_t len = ::strftime(×tr[0], timestr.size(), format.c_str(), &c_tm); - while (len == 0) { - if (timestr.size() >= 128) { - // strftime has failed for reasons unrelated to the size of the buffer - // so return a formatting error - return "ERROR"; - } - timestr.resize(timestr.size() * 2); - len = ::strftime(×tr[0], timestr.size(), format.c_str(), &c_tm); + char buf[128]; + size_t len = ::strftime(buf, sizeof(buf), format, &c_tm); + if (len > 0) { + return std::string(buf, len); } - timestr.resize(len); - return timestr; + return "ERROR"; } +std::string ESPTime::strftime(const std::string &format) { return this->strftime(format.c_str(), format.size()); } + bool ESPTime::strptime(const std::string &time_to_parse, ESPTime &esp_time) { uint16_t year; uint8_t month; diff --git a/esphome/core/time.h b/esphome/core/time.h index a53fca2346..0d47ce820b 100644 --- a/esphome/core/time.h +++ b/esphome/core/time.h @@ -55,6 +55,23 @@ struct ESPTime { */ std::string strftime(const std::string &format); + /** Convert this ESPTime struct to a string as specified by the format argument. + * @see https://www.gnu.org/software/libc/manual/html_node/Formatting-Calendar-Time.html#index-strftime + * + * This overload is optimized for string literals and avoids std::string parameter overhead. + * + * @param format The format string (null-terminated C string) + * @param format_len Optional length of the format string. If 0 (default), strlen() will be called. + * + * @warning This method uses dynamically allocated strings which can cause heap fragmentation with some + * microcontrollers. + * + * @warning This method can return "ERROR" when the underlying strftime() call fails, e.g. when the + * format string contains unsupported specifiers or when the format string doesn't produce any + * output. + */ + std::string strftime(const char *format, size_t format_len = 0); + /// Check if this ESPTime is valid (all fields in range and year is greater than 2018) bool is_valid() const { return this->year >= 2019 && this->fields_in_range(); }