mirror of https://github.com/Icinga/icinga2.git
LegacyTimePeriod::ScriptFunc: fix DST edge-cases
This change fixes two problems: * The internal functions used by ScriptFunc more or less expect to operate on full days, but ScriptFunc may have called them with some random timestamp during the day. This is fixed by always using midnight of the day as reference time. * Previously, the code advanced a timestamp to the next day by adding 24 hours. On days with DST changes, this could either still be on the same day (a day may have 25 hours) or skip an entire day (a day may have 23 hours). This is fixed by using a struct tm to advance the time to the next day.
This commit is contained in:
parent
e1c6c9eb19
commit
a740b1d66c
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue