mirror of
https://github.com/esphome/esphome.git
synced 2026-02-18 15:35:59 -07:00
tweak
This commit is contained in:
@@ -17,6 +17,23 @@ static uint32_t parse_uint(const char *&p) {
|
|||||||
|
|
||||||
bool is_leap_year(int year) { return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0); }
|
bool is_leap_year(int year) { return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0); }
|
||||||
|
|
||||||
|
// Extract just the year from a UTC epoch (faster than full epoch_to_tm_utc)
|
||||||
|
static int epoch_to_year(time_t epoch) {
|
||||||
|
int64_t days = epoch / 86400;
|
||||||
|
if (epoch < 0 && epoch % 86400 != 0)
|
||||||
|
days--;
|
||||||
|
int year = 1970;
|
||||||
|
while (days >= (is_leap_year(year) ? 366 : 365)) {
|
||||||
|
days -= is_leap_year(year) ? 366 : 365;
|
||||||
|
year++;
|
||||||
|
}
|
||||||
|
while (days < 0) {
|
||||||
|
year--;
|
||||||
|
days += is_leap_year(year) ? 366 : 365;
|
||||||
|
}
|
||||||
|
return year;
|
||||||
|
}
|
||||||
|
|
||||||
int days_in_month(int year, int month) {
|
int days_in_month(int year, int month) {
|
||||||
static const int DAYS_PER_MONTH[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
static const int DAYS_PER_MONTH[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||||
if (month == 2 && is_leap_year(year))
|
if (month == 2 && is_leap_year(year))
|
||||||
@@ -198,9 +215,7 @@ void day_of_year_to_month_day(int day_of_year, int year, int &out_month, int &ou
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool parse_dst_rule(const char *&p, DSTRule &rule) {
|
bool parse_dst_rule(const char *&p, DSTRule &rule) {
|
||||||
// Initialize defaults
|
rule = {}; // Zero initialize
|
||||||
rule = {};
|
|
||||||
rule.time_seconds = 2 * 3600; // Default 02:00
|
|
||||||
|
|
||||||
if (*p == 'M' || *p == 'm') {
|
if (*p == 'M' || *p == 'm') {
|
||||||
// M format: Mm.w.d (month.week.day)
|
// M format: Mm.w.d (month.week.day)
|
||||||
@@ -281,9 +296,7 @@ bool parse_posix_tz(const char *tz_string, ParsedTimezone &result) {
|
|||||||
|
|
||||||
// Check for DST name
|
// Check for DST name
|
||||||
if (!*p) {
|
if (!*p) {
|
||||||
// No DST
|
return true; // No DST
|
||||||
result.has_dst = false;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If next char is comma, there's no DST name but there are rules (invalid)
|
// If next char is comma, there's no DST name but there are rules (invalid)
|
||||||
@@ -292,9 +305,7 @@ bool parse_posix_tz(const char *tz_string, ParsedTimezone &result) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!internal::skip_tz_name(p)) {
|
if (!internal::skip_tz_name(p)) {
|
||||||
// No valid DST name, no DST
|
return true; // No valid DST name, no DST
|
||||||
result.has_dst = false;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have a DST name
|
// We have a DST name
|
||||||
@@ -363,19 +374,18 @@ time_t calculate_dst_transition(int year, const DSTRule &rule, int32_t base_offs
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build the tm struct for this date at the transition time
|
// Calculate days from epoch to this date
|
||||||
struct tm transition_tm = {};
|
int64_t days = 0;
|
||||||
transition_tm.tm_year = year - 1900;
|
for (int y = 1970; y < year; y++) {
|
||||||
transition_tm.tm_mon = month - 1;
|
days += internal::is_leap_year(y) ? 366 : 365;
|
||||||
transition_tm.tm_mday = day;
|
}
|
||||||
transition_tm.tm_hour = rule.time_seconds / 3600;
|
for (int m = 1; m < month; m++) {
|
||||||
transition_tm.tm_min = (rule.time_seconds % 3600) / 60;
|
days += internal::days_in_month(year, m);
|
||||||
transition_tm.tm_sec = rule.time_seconds % 60;
|
}
|
||||||
|
days += day - 1;
|
||||||
|
|
||||||
// Convert to UTC epoch, then add the base offset
|
// Convert to epoch and add transition time and base offset
|
||||||
// (transition times are specified in local time before the transition)
|
return days * 86400 + rule.time_seconds + base_offset_seconds;
|
||||||
time_t local_epoch = internal::tm_to_epoch_utc(&transition_tm);
|
|
||||||
return local_epoch + base_offset_seconds;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_in_dst(time_t utc_epoch, const ParsedTimezone &tz) {
|
bool is_in_dst(time_t utc_epoch, const ParsedTimezone &tz) {
|
||||||
@@ -383,10 +393,7 @@ bool is_in_dst(time_t utc_epoch, const ParsedTimezone &tz) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the year from the UTC epoch
|
int year = internal::epoch_to_year(utc_epoch);
|
||||||
struct tm utc_tm;
|
|
||||||
internal::epoch_to_tm_utc(utc_epoch, &utc_tm);
|
|
||||||
int year = utc_tm.tm_year + 1900;
|
|
||||||
|
|
||||||
// Calculate DST start and end for this year
|
// Calculate DST start and end for this year
|
||||||
// DST start transition happens in standard time
|
// DST start transition happens in standard time
|
||||||
|
|||||||
Reference in New Issue
Block a user