Choose one time primitive for one control decision
GotoIfTime() changes the channel's context, extension and priority when a time specification selects its true or false target. ExecIfTime() conditionally runs one application, while IFTIME() returns one of two values for later use. Those are different control contracts: a returned string is not a jump, an executed application is not proof of its result, and a selected jump is not proof that the final destination answered.
Write the business policy first, then choose the smallest primitive that expresses it. Keep generated FreePBX time-condition dialplan owned by FreePBX; use custom Asterisk logic only in an explicitly maintained custom context or integration boundary.
Treat every timespec field as part of the match
Asterisk documents a timespec with time, weekday, month-day and month fields plus an optional timezone. Preserve the exact text loaded for each field. A correct-looking hour can still choose the wrong branch because the weekday, date, month or zone excludes the call.
Define overnight windows and seasonal boundaries deliberately rather than assuming a range crosses midnight as an operator expects. For FreePBX, keep the selected Time Group and every range separate from the Time Condition and its two destinations; an unset day or month can mean all values, while the older Sangoma guide also documents blank time fields with a date range as an exclusion pattern.
Name the clock and timezone owner
Record the call timestamp, host clock, operating-system timezone, any explicit timespec timezone and the timezone used only for display. STRFTIME() can render a chosen epoch in a chosen zone, which is useful evidence, but a formatted value does not prove that the same zone controlled a separate condition.
Do not shift every schedule to compensate for a wrong host clock or timezone. Correct the supported owner in an approved window, preserve before-and-after values and verify both a time expression and the real call path after the change.
Resolve both targets before traffic reaches the decision
Asterisk says an omitted selected label produces no jump and execution continues to the next instruction. A bogus target follows the failure behavior of Goto(). Therefore, record the true target, false target, fall-through priority and whether each context, extension and priority exists in the loaded dialplan.
For nested time decisions, draw the order from the first condition to a named final destination. Holiday, ordinary-hours, evening and manual-closure decisions should not form a cycle or rely on an undocumented catch-all. A correct first match can still end at a wrong announcement, queue, voicemail or custom destination.
Use TESTTIME on a bounded diagnostic channel
TESTTIME(date,time[,zone]) sets an alternate logical time on the channel so time conditions can be evaluated away from the current instant. That is a channel test control, not permission to change the production host clock. Run it only in an isolated diagnostic context or a representative staging copy, and prevent the test path from dialing customers, emergency routes or chargeable destinations.
Exercise the instant before, at and after every opening or closing boundary, ordinary weekdays, weekends, fixed and floating holidays, daylight-saving transitions where relevant, and both explicit and host-default zones. Clear the test path and confirm a fresh ordinary channel uses real time afterward.
Prove selection, downstream handling and restoration separately
Log a correlation-safe channel identifier, displayed time and zone, exact timespec, chosen true, false or fall-through branch, loaded target and final caller treatment. Redact customer identities and avoid permanent verbose logging. Preserve an unrelated control route so a broad clock or configuration change cannot pass by merely moving the symptom.
Correct only the demonstrated owner, then retest both sides of the boundary and the restored scheduled state. A selected branch is not evidence of answer, prompt accuracy, queue admission, voicemail deposit or media. This guide is documentation-derived; no PBX, module, clock, timezone, dialplan, condition, override, destination or live call was tested.
Keep conditional routing failure explicit
If a time-based branch calls optional applications or custom subroutines, use the exception guide to choose an explicit return-status or exception contract.
A time predicate and an active-channel epoch wait solve different problems
Use the WaitUntil guide when one active channel must remain in its dialplan until a target instant, and preserve the conversion and status evidence.
Sources & applicability
Primary references for the technical details above. Operational examples and planning checklists are VoIP.info editorial guidance.
- Asterisk 22 GotoIfTime application ↗
- Asterisk 22 ExecIfTime application ↗
- Asterisk 22 IFTIME function ↗
- Asterisk 22 TESTTIME function ↗
- Asterisk 22 STRFTIME function ↗
- Sangoma: Time Conditions module overview ↗
- Sangoma: Time Conditions user guide ↗
- Sangoma: Time Group user guide ↗
- FreePBX Time Conditions release/17.0 metadata ↗
- Asterisk special dialplan extensions ↗
- Asterisk 23 RaiseException application ↗
- Asterisk 23 EXCEPTION function ↗
- Asterisk 23 TryExec application ↗
- Asterisk 23 WaitUntil application ↗
- Asterisk 22 WaitUntil application ↗
- Asterisk 23 TIMEOUT function ↗
- Asterisk 23 STRFTIME function ↗
- Asterisk 23 STRPTIME function ↗
Examples require adaptation to your topology. No live PBX or hardware testing is claimed.