diff --git a/lib/icinga/legacytimeperiod.cpp b/lib/icinga/legacytimeperiod.cpp index d8355110f..33e666544 100644 --- a/lib/icinga/legacytimeperiod.cpp +++ b/lib/icinga/legacytimeperiod.cpp @@ -586,13 +586,35 @@ Array::Ptr LegacyTimePeriod::ScriptFunc(const TimePeriod::Ptr& tp, double begin, Dictionary::Ptr ranges = tp->GetRanges(); if (ranges) { - for (int i = 0; i <= (end - begin) / (24 * 60 * 60); i++) { - time_t refts = begin + i * 24 * 60 * 60; - tm reference = Utility::LocalTime(refts); + tm tm_begin = Utility::LocalTime(begin); + + // Always evaluate time periods for full days as their ranges are given per day. + tm_begin.tm_hour = 0; + tm_begin.tm_min = 0; + tm_begin.tm_sec = 0; + tm_begin.tm_isdst = -1; + + // Helper to move a struct tm to midnight of the next day for the loop below. + // Due to DST changes, this may move the time by something else than 24 hours. + auto advance_to_next_day = [](tm *t) { + t->tm_mday++; + t->tm_hour = 0; + t->tm_min = 0; + t->tm_sec = 0; + t->tm_isdst = -1; + + // Normalize fields using mktime. + mktime(t); + + // Reset tm_isdst so that future calls figure out the correct time zone after setting tm_hour/tm_min/tm_sec. + t->tm_isdst = -1; + }; + + for (tm reference = tm_begin; mktime_const(&reference) <= end; advance_to_next_day(&reference)) { #ifdef I2_DEBUG Log(LogDebug, "LegacyTimePeriod") - << "Checking reference time " << refts; + << "Checking reference time " << mktime_const(&reference); #endif /* I2_DEBUG */ ObjectLock olock(ranges);