Time-Based Routing for Business Hours

Routing -- Last reviewed 2026-07-11 routing time-based business-hours dialplan gotoiftime after-hours Found this useful? Upvote it. ×

Time-Based Routing for Business Hours

Route inbound calls to the live queue during business hours and to voicemail (or an after-hours message) outside of them. Uses GotoIfTime() to evaluate the schedule without any external scripting.

Dialplan

[from-trunk]
exten => s,1,Answer()
 ; GotoIfTime(times|weekdays|mdays|months?label)
 ; Match Mon-Fri, 9:00 AM to 5:00 PM
 same => n,GotoIfTime(09:00-17:00|mon-fri|*|*?open,s,1)
 same => n,Goto(after-hours,s,1)

[open]
exten => s,1,Background(custom/thank-you-for-calling)
 same => n,WaitExten(5)

exten => 1,1,Dial(PJSIP/sales&PJSIP/support,30)
 same => n,Voicemail(sales@default,u)
 same => n,Hangup()

exten => 0,1,Dial(PJSIP/reception,30)
 same => n,Voicemail(reception@default,u)
 same => n,Hangup()

exten => i,1,Goto(s,1)
exten => t,1,Goto(s,1)

[after-hours]
exten => s,1,Playback(custom/after-hours)
 same => n,Voicemail(general@default,u)
 same => n,Hangup()

GotoIfTime syntax

GotoIfTime(times|weekdays|mdays|months?dest_if_true:dest_if_false)
Field Format Examples
times HH:MM-HH:MM 09:00-17:00, 08:30-12:00
weekdays Day names or * mon-fri, sat-sun, mon, *
mdays Day of month or * 1-15, *
months Month names or * jan-dec, dec, *

Use * for fields you do not care about. All four fields must be present.

Multiple schedules

Chain GotoIfTime() calls to handle lunch breaks, holidays, or split shifts:

[from-trunk]
exten => s,1,Answer()
 ; Morning shift
 same => n,GotoIfTime(08:00-12:00|mon-fri|*|*?open,s,1)
 ; Afternoon shift (skips 12:00-13:00 lunch)
 same => n,GotoIfTime(13:00-17:00|mon-fri|*|*?open,s,1)
 ; Saturday morning
 same => n,GotoIfTime(09:00-13:00|sat|*|*?open,s,1)
 ; Everything else
 same => n,Goto(after-hours,s,1)

Each GotoIfTime() jumps to open immediately on a match, so the chains work like an if/else-if ladder -- first match wins, remainder is not evaluated.

Testing the schedule

The schedule depends entirely on the server's local time. Verify it before going live:

# Check the server clock and timezone
timedatectl

# Trace the dialplan live -- connect with high verbosity and originate a test call
asterisk -rvvvv

From within the CLI session:

*CLI> channel originate Local/s@from-trunk application Wait 10

Watch the output. Each GotoIfTime() priority prints whether it matched or fell through, so you can confirm the correct branch is taken at any given time of day.

Tips

User Notes

Know a tip or gotcha for this topic? Share it below and help others.

Contribute a note

Share a tip, gotcha, or practical example. Keep it under 2000 characters. No questions (use the Asterisk community forums for support). Wrap code in backticks.

Moderated before publishing. Email never shown.
Related Snippets