Real-time planning: actual arrival and departure times
| This guide details the currently supported real-time planning features. If you are using the Patch (preview) feature, please see Real-time planning with patches |
There are many situations where Real-time planning is necessary.
During an active shift, a technician’s mobile app records the exact times when they arrived at a visit, started the work, and departed. When a re-plan is triggered mid-day, for example, because an urgent visit was added or a technician fell ill, those recorded times should used in the new plan. Without them, the solver would estimate those times from the previous plan, which may no longer reflect reality if the visit ran long or started late.
By providing the actual times on already-completed or in-progress visits, the solver anchors the re-plan to what actually happened in the field, producing a more accurate schedule for all remaining visits.
1. Actual time fields on itinerary items
Three optional fields are available on each itinerary item:
actualArrivalTime-
The actual time (ISO 8601 datetime with offset to UTC) when the vehicle arrived at the visit location.
actualStartServiceTime-
The actual time (ISO 8601 datetime with offset to UTC) when the vehicle started the service job for this visit.
actualDepartureTime-
The actual time (ISO 8601 datetime with offset to UTC) when the vehicle departed from the visit location.
All three fields are optional and can be set independently or in combination.
When an actual time is provided, the solver uses it directly instead of calculating it from the plan.
For example, if actualDepartureTime is set, the solver uses that value as the start of travel to the next visit, regardless of the planned departure time.
2. Minimum JSON
Add actual times to an itinerary item under a vehicle shift:
{
"modelInput": {
"vehicles": [
{
"id": "Carl",
"shifts": [
{
"id": "Carl-2027-02-01",
"startLocation": [33.68786, -84.18487],
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z",
"itinerary": [
{
"id": "Visit E",
"kind": "VISIT",
"actualArrivalTime": "2027-02-01T09:52:00Z",
"actualStartServiceTime": "2027-02-01T09:55:00Z",
"actualDepartureTime": "2027-02-01T12:10:00Z"
},
{
"id": "Visit B",
"kind": "VISIT"
}
]
}
]
}
]
}
}
In this example, Visit E has already been completed. The solver uses the actual times when calculating the schedule for Visit B and any subsequent visits.
3. Typical re-planning scenario
Consider the following situation:
-
Carl has three visits scheduled: Visit E, Visit B, and Visit D.
-
Visit E is complete. Carl’s mobile app recorded that he arrived at 09:52, started work at 09:55, and departed at 12:10, two hours later than planned.
-
A re-plan is triggered to update the rest of Carl’s day.
The re-planning input includes:
-
The actual times for Visit E.
-
freezeTimeto lock completed and in-progress portions of the schedule:{ "modelInput": { "freezeTime": "2027-02-01T12:15:00Z" } } -
The itinerary with all visits, and
minStartTravelTimeset, as provided by the initial planning runs.
The solver uses actualDepartureTime from Visit E as the earliest possible start of travel to Visit B.
This ensures the re-planned schedule for Visit B and Visit D reflects the true elapsed time in the field.
4. Pinning visits before the visit with actuals
When actual times are set on a visit, Timefold automatically pins that visit and all visits that appear before it in the shift itinerary.
No explicit pinning or freezeTime is required for this.
In the following example, Carl’s itinerary contains Visit A, Visit E (with actuals), and Visit B. Timefold automatically pins Visit A and Visit E, while leaving Visit B free to be rescheduled:
{
"modelInput": {
"vehicles": [
{
"id": "Carl",
"shifts": [
{
"id": "Carl-2027-02-01",
"startLocation": [33.68786, -84.18487],
"minStartTime": "2027-02-01T09:00:00Z",
"maxEndTime": "2027-02-01T17:00:00Z",
"itinerary": [
{
"id": "Visit A",
"kind": "VISIT"
},
{
"id": "Visit E",
"kind": "VISIT",
"actualArrivalTime": "2027-02-01T09:52:00Z",
"actualStartServiceTime": "2027-02-01T09:55:00Z",
"actualDepartureTime": "2027-02-01T12:10:00Z"
},
{
"id": "Visit B",
"kind": "VISIT"
}
]
}
]
}
]
}
}
See Real-time planning: pinning visits for details on additional pinning options.
|
Actual times are not supported on breaks. If actual times are set on a break itinerary item, they will be ignored and a warning ( |
5. Breaks overlapping with actual times
When a visit has actual times and its schedule overlaps with a scheduled fixed break, the break is automatically handled based on the actual departure time.
A fixed break is applied to a visit’s schedule only if it ends at or before the actual departure time. If the break ends after the actual departure — meaning the visit extended into or beyond the break window — the break is silently skipped for that visit and treated as a remaining break to be applied to a later point in the shift.
For example, if a fixed lunch break runs from 12:00 to 13:00 and the technician’s actualDepartureTime is 12:30:
-
The break ends at 13:00, which is after the departure at 12:30.
-
The break is not applied to this visit’s schedule.
-
The break becomes a remaining break, which the next visit’s schedule calculation may apply.
This reflects what actually happened in the field: if the technician’s work extended into a break window, the break did not occur at that time. Timefold does not automatically reschedule the missed break, and no warning is issued.
If the missed break must still be taken — for example, a legally required rest — adjust the break’s time window in the input so that it falls after the actual departure time. This keeps you in full control of when the break is rescheduled.
6. Impact of actual times on metrics
When actual times are provided, Timefold uses them to compute more realistic values for the metrics fields in the plan output.
For visits with actual times, the following metrics are derived from the recorded timestamps rather than from the scheduling variables:
totalTravelTime/travelTimeFromStartLocationToFirstVisit/travelTimeBetweenVisits-
Derived as the difference between the visit’s
actualArrivalTimeand the previous stop’s departure time (actual or planned). totalServiceDuration-
Derived as the difference between
actualDepartureTimeandactualStartServiceTime. totalWaitingTime-
Derived as the difference between
actualStartServiceTimeandactualArrivalTime.
All derived values are clamped to zero. This handles situations where overlapping actual timestamps would otherwise produce a negative duration — for example, when a technician’s mobile app records an arrival time before the previous visit’s recorded departure time.
6.1. Metrics inconsistency when clamping occurs
Clamping prevents negative durations but introduces a different problem: the clamped metric no longer reflects reality, and there is no signal in the output that clamping occurred. Any metric that is clamped silently transfers its "missing" time into the unaccounted part of the shift.
Consider the following example:
-
Visit E:
actualDepartureTime=2027-02-01T12:10:00Z -
Visit B:
actualArrivalTime=2027-02-01T12:05:00Z
The computed travel time between Visit E and Visit B is 12:05 − 12:10 = −5 minutes.
After clamping, travelTimeBetweenVisits (and totalTravelTime) report PT0S for this leg.
Carl clearly did travel between the two locations, but the metrics show zero travel time.
The five missing minutes are not redistributed to another metric category; they simply disappear from the totals.
As a result, totalTravelTime for the shift is understated, and adding up individual metric components will not equal the total shift duration.
The same principle applies to the other clamped metrics:
-
A
totalServiceDurationofPT0Scan mean the visit had no service time, or thatactualDepartureTimewas recorded beforeactualStartServiceTime. -
A
totalWaitingTimeofPT0Scan mean the technician started work immediately, or thatactualStartServiceTimewas recorded beforeactualArrivalTime.
|
Actual times improve the realism of metrics when the recorded data accurately reflects what happened in the field. However, they also make metrics sensitive to data quality. Inaccurate or inconsistent timestamps — such as a departure time recorded before the start-of-service time, or an arrival time recorded before the previous departure — will produce misleading metrics. Validate actual times before feeding them back into a re-plan to ensure metrics remain meaningful. When any clamped metric is zero, treat it as a potential data quality issue rather than a definitive observation. |
Next
-
See the full API spec or try the online API.
-
Learn more about field service routing from our YouTube playlist.
-
Learn about real-time planning.
-
Real-time planning with extended visits.
-
Real-time planning with pinned visits.