5#ifdef USE_TIME_TIMEZONE
12 static const uint8_t DAYS_IN_MONTH[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
15 return DAYS_IN_MONTH[
month];
19 struct tm c_tm = this->
to_c_tm();
20#ifdef USE_TIME_TIMEZONE
25 bool needs_subst =
false;
26 for (
const char *p =
format; *p; p++) {
27 if (*p ==
'%' && *(p + 1)) {
31 if (*p ==
'Z' || *p ==
'z') {
45 char *out_end = modified +
sizeof(modified) - 1;
46 for (
const char *p =
format; *p && out < out_end; p++) {
48 if (*(p + 1) ==
'%') {
53 }
else if (*(p + 1) ==
'Z' || *(p + 1) ==
'z') {
55 for (
const char *d = designation; *d && out < out_end; d++)
65 return ::strftime(buffer, buffer_len, modified, &c_tm);
68 return ::strftime(buffer, buffer_len,
format, &c_tm);
77 constexpr char error_str[] =
"ERROR";
78 std::copy_n(error_str,
sizeof(error_str), buffer.data());
79 return sizeof(error_str) - 1;
84 res.
second = uint8_t(c_tm->tm_sec);
85 res.minute = uint8_t(c_tm->tm_min);
86 res.hour = uint8_t(c_tm->tm_hour);
87 res.day_of_week = uint8_t(c_tm->tm_wday + 1);
88 res.day_of_month = uint8_t(c_tm->tm_mday);
89 res.day_of_year = uint16_t(c_tm->tm_yday + 1);
90 res.month = uint8_t(c_tm->tm_mon + 1);
91 res.year = uint16_t(c_tm->tm_year + 1900);
92 res.is_dst = bool(c_tm->tm_isdst);
93 res.timestamp = c_time;
99 c_tm.tm_sec = this->
second;
100 c_tm.tm_min = this->
minute;
101 c_tm.tm_hour = this->
hour;
102 c_tm.tm_mday = this->day_of_month;
103 c_tm.tm_mon = this->
month - 1;
104 c_tm.tm_year = this->
year - 1900;
105 c_tm.tm_wday = this->day_of_week - 1;
106 c_tm.tm_yday = this->day_of_year - 1;
107 c_tm.tm_isdst = this->is_dst;
114 return std::string(buf,
len);
120static bool parse_digits(
const char *&p,
const char *
end,
int count, uint16_t &value) {
122 for (
int i = 0; i < count; i++) {
123 if (p >=
end || *p <
'0' || *p >
'9')
125 value = value * 10 + (*p -
'0');
132static bool expect_char(
const char *&p,
const char *
end,
char expected) {
133 if (p >=
end || *p != expected)
147 if (time_to_parse ==
nullptr ||
len == 0)
150 const char *p = time_to_parse;
151 const char *
end = time_to_parse +
len;
152 uint16_t v1, v2, v3, v4, v5, v6;
155 if (
len >= 10 && time_to_parse[4] ==
'-') {
157 if (!parse_digits(p,
end, 4, v1))
159 if (!expect_char(p,
end,
'-'))
161 if (!parse_digits(p,
end, 2, v2))
163 if (!expect_char(p,
end,
'-'))
165 if (!parse_digits(p,
end, 2, v3))
177 if (!expect_char(p,
end,
' '))
181 if (!parse_digits(p,
end, 2, v4))
183 if (!expect_char(p,
end,
':'))
185 if (!parse_digits(p,
end, 2, v5))
197 if (!expect_char(p,
end,
':'))
199 if (!parse_digits(p,
end, 2, v6))
207 if (
len >= 5 && time_to_parse[2] ==
':') {
208 if (!parse_digits(p,
end, 2, v1))
210 if (!expect_char(p,
end,
':'))
212 if (!parse_digits(p,
end, 2, v2))
224 if (!expect_char(p,
end,
':'))
226 if (!parse_digits(p,
end, 2, v3))
257 uint16_t days_in_year = (this->
year % 4 == 0) ? 366 : 365;
275 uint16_t days_in_year = (this->
year % 4 == 0) ? 366 : 365;
289 for (
int i = 1970; i < this->
year; i++)
290 res += (i % 4 == 0) ? 366 : 365;
292 if (use_day_of_year) {
295 for (
int i = 1; i < this->
month; i++)
310#ifdef USE_TIME_TIMEZONE
336 if (dst_valid && !std_valid) {
354#ifdef USE_TIME_TIMEZONE
355 time_t now = ::time(
nullptr);
377 if (current >=
end) {
bool is_in_dst(time_t utc_epoch, const ParsedTimezone &tz)
Check if a given UTC epoch falls within DST for the parsed timezone.
const ParsedTimezone & get_global_tz()
Get the global timezone.
void format_designation(int32_t posix_offset, char *buf, size_t buf_size)
Format a POSIX offset as "+HHMM"/"-HHMM" into buf (must be >= 6 bytes).
Providing packet encoding functions for exchanging data with a remote host.
const char int const __FlashStringHelper * format
uint8_t days_in_month(uint8_t month, uint16_t year)
bool increment_time_value(T ¤t, uint16_t begin, uint16_t end)
A more user-friendly version of struct tm from time.h.
void increment_second()
Increment this clock instance by one second.
static int32_t timezone_offset()
uint8_t minute
minutes after the hour [0-59]
void recalc_timestamp_utc(bool use_day_of_year=true)
Recalculate the timestamp field from the other fields of this ESPTime instance (must be UTC).
bool operator<(const ESPTime &other) const
uint8_t second
seconds after the minute [0-60]
size_t strftime(char *buffer, size_t buffer_len, const char *format)
Convert this ESPTime struct to a null-terminated c string buffer as specified by the format argument.
bool fields_in_range(bool check_day_of_week=true, bool check_day_of_year=true) const
Check if time fields are in range.
size_t strftime_to(std::span< char, STRFTIME_BUFFER_SIZE > buffer, const char *format)
Format time into a fixed-size buffer, returns length written.
bool operator>(const ESPTime &other) const
uint8_t hour
hours since midnight [0-23]
time_t timestamp
unix epoch time (seconds since UTC Midnight January 1, 1970)
void increment_day()
Increment this clock instance by one day.
uint16_t day_of_year
day of the year [1-366]
static ESPTime from_c_tm(struct tm *c_tm, time_t c_time)
Convert a C tm struct instance with a C unix epoch timestamp to an ESPTime instance.
static bool strptime(const char *time_to_parse, size_t len, ESPTime &esp_time)
Convert a string to ESPTime struct as specified by the format argument.
bool operator<=(const ESPTime &other) const
bool operator==(const ESPTime &other) const
void recalc_timestamp_local()
Recalculate the timestamp field from the other fields of this ESPTime instance assuming local fields.
static constexpr size_t STRFTIME_BUFFER_SIZE
Buffer size required for strftime output.
uint8_t day_of_month
day of the month [1-31]
struct tm to_c_tm()
Convert this ESPTime instance back to a tm struct.
uint8_t month
month; january=1 [1-12]
bool operator>=(const ESPTime &other) const
uint8_t day_of_week
day of the week; sunday=1 [1-7]
bool has_dst() const
Check if this timezone has DST rules.
int32_t dst_offset_seconds
DST offset from UTC in seconds.
int32_t std_offset_seconds
Standard time offset from UTC in seconds (positive = west)