Overview
Time windows define when jobs can be serviced, ensuring resources arrive within specified time ranges. This feature enables you to meet customer expectations, comply with delivery agreements, and optimize routes while respecting temporal constraints.
The VRP solver automatically ensures resources arrive at the beginning of time windows, eliminating early arrivals and unnecessary waiting.
Time Window Configuration
Basic Structure
Each job can have multiple time windows, providing flexibility for service scheduling:
{
"name" : "delivery-123" ,
"duration" : 3600 ,
"windows" : [
{
"from" : "2023-01-02T09:00:00" ,
"to" : "2023-01-02T10:00:00" ,
"hard" : true ,
"weight" : 100
}
]
}
Window Properties
Start time of the window in ISO 8601 format. The resource cannot arrive before this time.
End time of the window in ISO 8601 format. The resource must arrive before this time.
Whether violating this window makes the solution infeasible. Hard windows must be respected.
Penalty weight applied when soft windows are violated. Higher values increase violation cost.
Complete Example
This example demonstrates time window usage with partial planning enabled, showing how some jobs may remain unassigned due to time constraints.
Request Solution Explanation {
"resources" : [
{
"name" : "R-1" ,
"shifts" : [
{
"from" : "2023-01-01T08:00:00" ,
"to" : "2023-01-01T17:00:00"
},
{
"from" : "2023-01-02T08:00:00" ,
"to" : "2023-01-02T17:00:00"
}
]
}
],
"jobs" : [
{
"name" : "JOB-1" ,
"location" : {
"latitude" : 50.54963315022148 ,
"longitude" : 4.848855475505483
},
"duration" : 3600 ,
"windows" : [
{
"from" : "2023-01-02T09:00:00" ,
"to" : "2023-01-02T10:00:00" ,
"hard" : true ,
"weight" : 100
}
]
},
{
"name" : "JOB-2" ,
"location" : {
"latitude" : 50.65910297910443600 ,
"longitude" : 4.007987934186738
},
"duration" : 3600 ,
"windows" : [
{
"from" : "2023-01-02T09:30:00" ,
"to" : "2023-01-02T10:30:00" ,
"hard" : true ,
"weight" : 100
}
]
},
{
"name" : "JOB-3" ,
"location" : {
"latitude" : 50.324969095932296 ,
"longitude" : 4.010111317974326
},
"duration" : 3600
// No time window - can be scheduled anytime
},
// Additional jobs 4-10...
],
"options" : {
"partialPlanning" : true
}
}
{
"resources" : [
{
"name" : "R-1" ,
"shifts" : [
{
"from" : "2023-01-01T08:00:00" ,
"to" : "2023-01-01T17:00:00"
},
{
"from" : "2023-01-02T08:00:00" ,
"to" : "2023-01-02T17:00:00"
}
]
}
],
"jobs" : [
{
"name" : "JOB-1" ,
"location" : {
"latitude" : 50.54963315022148 ,
"longitude" : 4.848855475505483
},
"duration" : 3600 ,
"windows" : [
{
"from" : "2023-01-02T09:00:00" ,
"to" : "2023-01-02T10:00:00" ,
"hard" : true ,
"weight" : 100
}
]
},
{
"name" : "JOB-2" ,
"location" : {
"latitude" : 50.65910297910443600 ,
"longitude" : 4.007987934186738
},
"duration" : 3600 ,
"windows" : [
{
"from" : "2023-01-02T09:30:00" ,
"to" : "2023-01-02T10:30:00" ,
"hard" : true ,
"weight" : 100
}
]
},
{
"name" : "JOB-3" ,
"location" : {
"latitude" : 50.324969095932296 ,
"longitude" : 4.010111317974326
},
"duration" : 3600
// No time window - can be scheduled anytime
},
// Additional jobs 4-10...
],
"options" : {
"partialPlanning" : true
}
}
{
"score" : {
"hardScore" : 0 ,
"mediumScore" : -3600 ,
"softScore" : -21334 ,
"feasible" : true
},
"trips" : [
{
"visits" : [
{
"arrival" : "2023-01-02T08:00:00" ,
"job" : "JOB-9" ,
"location" : "50.09960152277046;4.465866983600702"
},
{
"arrival" : "2023-01-02T10:18:01" ,
"job" : "JOB-2" ,
"location" : "50.65910297910444;4.007987934186738"
},
{
"arrival" : "2023-01-02T12:13:45" ,
"job" : "JOB-6" ,
"location" : "50.89633806889935;4.45161298168845"
},
{
"arrival" : "2023-01-02T13:59:47" ,
"job" : "JOB-4" ,
"location" : "50.53457539132416;4.69167867847318"
}
],
"resource" : "R-1" ,
"date" : "2023-01-02" ,
"workTime" : 25187 ,
"serviceTime" : 14400
},
{
"visits" : [
{
"arrival" : "2023-01-01T08:00:00" ,
"job" : "JOB-8"
},
{
"arrival" : "2023-01-01T09:50:38" ,
"job" : "JOB-3"
},
{
"arrival" : "2023-01-01T11:33:03" ,
"job" : "JOB-7"
},
{
"arrival" : "2023-01-01T13:23:15" ,
"job" : "JOB-10"
},
{
"arrival" : "2023-01-01T14:55:42" ,
"job" : "JOB-5"
}
],
"resource" : "R-1" ,
"date" : "2023-01-01" ,
"workTime" : 28542 ,
"serviceTime" : 18000
}
],
"unserved" : [
"JOB-1" // Could not meet time window constraint
],
"status" : "SOLVED"
}
{
"score" : {
"hardScore" : 0 ,
"mediumScore" : -3600 ,
"softScore" : -21334 ,
"feasible" : true
},
"unresolved" : [
{
"constraint" : "JOB_DAY_INDEX" ,
"score" : "-5soft"
},
{
"constraint" : "TRAVEL_TIME" ,
"score" : "-21329soft"
},
{
"constraint" : "UNUSED_RESOURCES" ,
"score" : "-3600medium"
}
]
}
Key Insights
Why JOB-1 Was Unassigned
JOB-1 required service between 09:00-10:00 on 2023-01-02, but the route structure made it impossible to reach this location within the time window while also servicing JOB-2 (09:30-10:30).
The solver prioritized JOB-2 over JOB-1 based on overall route efficiency and the ability to service more total jobs.
Route Optimization Strategy
The solver:
Grouped jobs without time windows on Day 1 for maximum flexibility
Scheduled time-windowed jobs on Day 2 where feasible
Optimized travel paths to minimize total distance
Left JOB-1 unassigned rather than violating hard constraints
Time Window Patterns
Single Narrow Window
For strict appointment times:
{
"windows" : [{
"from" : "2023-01-15T14:00:00" ,
"to" : "2023-01-15T14:30:00" ,
"hard" : true
}]
}
Multiple Windows
For flexible scheduling options:
{
"windows" : [
{
"from" : "2023-01-15T09:00:00" ,
"to" : "2023-01-15T12:00:00" ,
"hard" : true
},
{
"from" : "2023-01-15T14:00:00" ,
"to" : "2023-01-15T17:00:00" ,
"hard" : true
}
]
}
Soft Windows with Preferences
For preferred but flexible timing:
{
"windows" : [
{
"from" : "2023-01-15T09:00:00" ,
"to" : "2023-01-15T10:00:00" ,
"hard" : false ,
"weight" : 50 // Moderate preference
},
{
"from" : "2023-01-15T08:00:00" ,
"to" : "2023-01-15T17:00:00" ,
"hard" : true // Must be within business hours
}
]
}
Best Practices
Use realistic window sizes
Allow sufficient time for travel and service. Overly narrow windows reduce routing flexibility and may lead to unassigned jobs.
Combine hard and soft windows
Use soft windows for preferences and hard windows for absolute requirements. This provides flexibility while meeting critical constraints.
Consider travel time
Account for realistic travel times between locations when setting consecutive time windows.
Enable partial planning
Set partialPlanning: true
when time windows might make complete assignment impossible. This prevents infeasible solutions.
Common Pitfalls
Overlapping windows causing conflicts
When multiple jobs have overlapping time windows in the same area, ensure there’s enough capacity to service them all:
// Problematic: Both require 09:00-10:00 slot
[
{ "name" : "job1" , "windows" : [{ "from" : "09:00" , "to" : "10:00" }]},
{ "name" : "job2" , "windows" : [{ "from" : "09:00" , "to" : "10:00" }]}
]
// Better: Stagger the windows
[
{ "name" : "job1" , "windows" : [{ "from" : "09:00" , "to" : "10:00" }]},
{ "name" : "job2" , "windows" : [{ "from" : "10:00" , "to" : "11:00" }]}
]
Impossible window sequences
Avoid setting windows that are physically impossible to achieve:
// Impossible: 30 minutes apart, 60 minutes travel time
{
"job1" : {
"location" : "cityA" ,
"windows" : [{ "from" : "09:00" , "to" : "09:30" }]
},
"job2" : {
"location" : "cityB" , // 60 min from cityA
"windows" : [{ "from" : "09:30" , "to" : "10:00" }]
}
}