Time-Based Routing for Business Hours
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
- Asterisk uses the server's local time. Verify your server timezone with
timedatectland make sure it matches your business location. - For holiday handling, set a global variable in
[globals](e.g.,HOLIDAY=1) and check it withGotoIf($[${HOLIDAY}=1]?after-hours,s,1)before theGotoIfTime()calls. Flip it in the CLI withasterisk -rx "dialplan set global HOLIDAY 1"when you close for the day. - The
IFTIME()dialplan function is an alternative that returns a value instead of branching; useful when you want to store the result and branch later:Set(OPEN=${IFTIME(09:00-17:00|mon-fri|*|*?1:0)}).
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.