A timeperiod is a named schedule: a set of weekly ranges, a handful of date exceptions for the days that do not follow the weekly pattern, and an optional list of other periods to exclude from it. Four things in a config can reference one by name: when a check runs, when a policy may notify, when an escalation level may notify, and when a contact is reachable.

1. What a timeperiod is

A timeperiod carries a name, a timezone, a map of ranges, and an exclude list.

timezone: "Europe/Madrid"

timeperiods: {
	office: {
		ranges: {
			monday:       "09:00-17:00"
			tuesday:      "09:00-17:00"
			wednesday:    "09:00-17:00"
			thursday:     "09:00-17:00"
			friday:       "09:00-17:00"
			"2026-12-25": "00:00-00:00"
			"january 1":  "00:00-00:00"
		}
	}
	maintenance: {
		timezone: "UTC"
		ranges: {"day 1": "02:00-04:00"}
	}
	office_no_maint: {
		ranges:  office.ranges
		exclude: ["maintenance"]
	}
}

Each key under ranges is a date expression; its value is a time list for the days that expression selects. exclude names other timeperiods whose open time is carved out of this one, the way maintenance above closes office_no_maint for two hours on the first of every month even though office's weekly ranges say nothing about it.

2. The range syntax

Every key is one of six forms, written the way an operator coming from Nagios already writes them.

Form Example Selects
a weekday monday that weekday, every week
a calendar date 2026-12-25, 2026-01-01 - 2026-01-10 / 3 one date, or a date span, with an optional stride
a month day july 4, july 4 - july 10 / 2 a day of a fixed month, or a span across months with a stride
a day of the month day 21, day 1 - 15 / 2, day -1 a day number counted from the start or, negative, from the end of the month
a nth weekday of a month monday 3 july, monday 1 july - friday 2 july the nth occurrence of a weekday in a month
a nth weekday, any month monday 3, monday 1 - friday 3 / 2, monday -1 the nth occurrence of a weekday in every month

Each key's value is a time list: comma-separated start-end pairs in 24-hour HH:MM, unpadded hours allowed, end may be 24:00. A pair does not wrap past midnight, so an overnight shift is two pairs on consecutive days: 22:00-24:00 under one date or weekday key and 00:00-06:00 under the next. An empty value or 00:00-00:00 closes the day, which is how a single date in the middle of an otherwise open week is turned into a holiday. / n after a span, where a form allows one, keeps the span's first day and then every n-th day after it; negative day numbers and negative occurrence counts count from the end.

3. How a day resolves

For a given civil date, the dated forms are checked before the weekly one, in a fixed order: calendar date, then month day, then day of the month, then nth weekday of a month, then nth weekday of any month. The first form whose key matches the date wins, and its time list is the day's ranges; within one kind of form, the rules are consulted in the lexical order of the ranges keys, since a CUE map has no declaration order. If nothing dated matches, the weekday rule for that day applies. If nothing matches at all, the day is closed. A date inside an excluded timeperiod is closed regardless of what its own ranges say.

4. Zones and daylight saving

Every timeperiod reads its ranges in an IANA zone. The top-level timezone sets the default every timeperiod inherits; a timeperiod's own timezone overrides it for that one period. The default is "Local", the process's own zone, because that is the value Nagios used and a config carried over should keep behaving as it did. A cluster whose engines run in different zones should set the top-level timezone explicitly rather than rely on each engine's own clock to agree.

Times inside a timeperiod are wall-clock, so a spring-forward gap and a fall-back repeat both need a rule. A range whose start falls inside a gap that daylight saving removes begins at the first instant after the gap. A range whose start falls in an hour that daylight saving repeats begins at the first occurrence of that wall-clock time.

5. The four references

  • check_period on a check. Outside it, the next check is deferred to the period's next open instant rather than run: nothing runs and nothing wakes up to find the period still closed. A forced recheck ignores it and runs anyway.
  • period on a notification policy. Outside it, the policy is suppressed with OUTSIDE_PERIOD.
  • period on an escalation level. Outside it, that level is suppressed with OUTSIDE_PERIOD.
  • notification_period on a contact. Outside it, the contact is dropped from whichever level would have notified it.

Each of the four takes a timeperiod name and defaults to empty, which means always: a check with no check_period runs on its own schedule regardless of the calendar, and a policy, level or contact with no period assigned is never gated by one.