Flexible start time (FlexTime and StartReductionTime)

Illustration on a dark street grid: two rows, each with a person icon and a shift bar that leads to a building; dashed segments show the start of the shift moved earlier in one row and later in the other, within marked limits

This guide describes the flexible start time: the start of a resource's working hours becomes a bounded time window that the optimizer can shift, later to cut idle time (FlexTime) or earlier for the drive to the first node (StartReductionTime). It is written for developers who model resources and their working hours in Java. The Resources page describes working hours and the other resource settings.

Table of contents

What it does

By default, the route of a resource starts at the fixed start of its working hours, for example 8:00 AM. This causes two problems. If the first node opens later than the shift start, the resource accumulates idle time. If the first node opens at the shift start and the drive takes 30 minutes, the resource arrives 30 minutes after the node opens.

FlexTime and StartReductionTime turn the start of the working hours into a bounded time window that the optimizer can shift within:

  • FlexTime shifts the start later. If the first node opens at 10:00, the resource does not have to idle from 8:00 to 10:00. With 2 hours of FlexTime, the optimizer can start the route at 9:15, drive 45 minutes and arrive at 10:00 with no idle time.
  • StartReductionTime shifts the driving start earlier. If the first node opens at 8:00 and the drive takes 30 minutes, the resource can leave at 7:30 and arrive at 8:00 ready to work, instead of arriving at 8:30.

Both are set per resource and per working hours, and both are hard constrained. The optimizer uses as much of them as is beneficial, up to the configured maximum. Schedules then show less idle time, and with StartReductionTime their Gantt charts start with work instead of a drive.

FlexTime: start later

A resource starts at 8:00 AM. The first node opens at 10:00 AM, and the drive takes 45 minutes. Without FlexTime, the resource leaves at 8:00, arrives at 8:45 and waits until 10:00: 1 hour and 15 minutes of idle time at the beginning of the shift.

With 2 hours of FlexTime, the resource can start up to 2 hours after its working hours begin, and the optimizer chooses the start time. In this case, it starts at 9:15, drives 45 minutes, arrives at 10:00 and begins work at once. The idle time drops to zero.

Gantt chart of resource John in three rows: without FlexTime, with one hour and with two hours of it; the idle time before the first node, which opens at 10 am, shrinks and then disappears

Figure 1: Three scenarios. Top: no FlexTime, full idle time. Center: 1 hour of FlexTime, part of the idle time remains. Bottom: 2 hours of FlexTime, no idle time.

StartReductionTime: start earlier

A node opens at 8:00 AM, and the resource also starts at 8:00 AM. The drive to the first node takes 30 minutes, so the resource arrives at 8:30. It is not late if the node's time window extends beyond 8:30, but the first 30 minutes of the shift are spent driving, and the node could have been served at 8:00.

With StartReductionTime, the optimizer may start the drive before the working hours begin. With up to 1 hour of StartReductionTime, the resource leaves at 7:30, drives 30 minutes and arrives at 8:00 when the node opens. The workday begins with productive time instead of a drive.

Gantt chart of resource John with StartReductionTime: the drive to the first node takes place before 8 am, and the first visit starts at 8 am

Figure 2: With StartReductionTime, the resource drives before its working hours start and arrives when the first node opens.

StartReductionTime also changes the Gantt chart of a plan. Without it, routes begin with long drives that push productive work later. With it, the first nodes of each route align to their opening hours.

Gantt charts of four resources, John, Lily, Bob and Alice, without and with StartReductionTime; with it, the first visits start at 8 am except for Bob

Figure 3: Four resources. Top: without StartReductionTime, every route starts with a drive. Bottom: with StartReductionTime, the first nodes align to their opening hours. Exception: Bob's StartReductionTime is not long enough to reach his first node when it opens.

Combining FlexTime and StartReductionTime

FlexTime and StartReductionTime can be used together on the same resource and working hours. The start of the working hours becomes a flexible band: it may shift later to avoid idle time, or earlier, for driving, to reach nodes that open early.

The optimizer picks the adjustment per day and per route, based on the actual first node and the travel time. On Monday, the first node might open late, and FlexTime is used. On Tuesday, it might open early, and StartReductionTime is used. The resource and its configuration stay the same.

When to use it

  • Field service where the first appointments open late: FlexTime reduces the idle time.
  • Delivery operations where docks open early and an early arrival is desirable: StartReductionTime.
  • Any operation where a route looks wrong because its start time is too rigid.
  • Tight time windows, where FlexTime and StartReductionTime can improve feasibility without a larger compute budget.

Use FlexTime and StartReductionTime instead of cost tuning. They expand the feasible region of the problem; do not simulate it with idle-time penalties. If you need strict behavior, such as "must not start before X", model it structurally.

How to use it

FlexTime in Java

setFlexTime on the resource sets the maximum FlexTime:

resource.setFlexTime(Duration.ofHours(2));

The resource can now start up to 2 hours after its working hours begin.

StartReductionTime in Java

setMaxRouteStartReductionTime sets the maximum StartReductionTime, and setReductionTimeIsIncludedInWorkingTime sets whether it counts as working time:

// Allow starting up to 1 hour earlier, driving only (no early work)
resource.setMaxRouteStartReductionTime(Duration.ofHours(1), true);
resource.setReductionTimeIsIncludedInWorkingTime(true);

The resource can now leave up to 1 hour before its working hours start.

Driving-only flag

The boolean parameter isOnlyUsedForDriving in setMaxRouteStartReductionTime(duration, isOnlyUsedForDriving) controls what the resource may do during the early start:

// true: early time can ONLY be used for driving to the first node
resource.setMaxRouteStartReductionTime(Duration.ofHours(1), true);

// false: early time can be used for driving AND working
resource.setMaxRouteStartReductionTime(Duration.ofHours(1), false);

With true, the resource may leave early to reach the first node, but productive work starts at the start of its working hours or at the node's opening hours, whichever applies. This models employees who leave home earlier to drive (commute, positioning) while their contractual work starts at the shift start.

With false, the resource can use the early time for driving and for working: a technician can leave earlier, arrive at the first node and start work at once, even before the official shift start. This gives the optimizer the most room, and it needs a labor policy that permits early productive work.

Working time inclusion

setReductionTimeIsIncludedInWorkingTime(boolean) controls whether the early driving time counts toward the working time of the resource:

// true: early driving counts as working time (common when early driving is paid)
resource.setReductionTimeIsIncludedInWorkingTime(true);

With true, the early start uses up working time. This fits operations where early driving is paid and subject to working-time regulations. With false, the early driving lies outside the working time. This is less common and used in some field-service operations where commute time is not paid.

Driving time and FlexTime

FlexTime has no driving-time setting: setFlexTime takes a duration only, and the FlexTime used is the time the resource would otherwise wait at its first node. The driving-time setting belongs to StartReductionTime: with isOnlyUsedForDriving (see Driving-only flag), the early time serves only the drive to the first node. This distinction matters for operations that differentiate between paid driving time and paid working time.

Early arrival at the first node

The node setting setWaitOnEarlyArrival(boolean), read with isWaitOnEarlyArrival, controls whether a resource that arrives before a node's opening hours must wait or can start work at once; setWaitOnEarlyArrivalFirstNode(boolean) does the same for the first node of a route. These settings interact with FlexTime:

  • If early work is allowed and FlexTime is used, the resource might start later and still begin working immediately on arrival (before the node's official opening).
  • If waiting is required, FlexTime adjustments target the moment the node opens, not just the arrival time.

Modeling guidance

  • Be explicit about the driving-only policy. For StartReductionTime, isOnlyUsedForDriving=true prevents productive work before the official shift start. Set it to false only if your labor policy permits early productive work. The difference matters for compliance and payroll.
  • Decide whether early driving counts as working time. Set setReductionTimeIsIncludedInWorkingTime by your labor rules, your payroll policy and your definition of maximum working time. A wrong setting can produce plans that violate working-time regulations.
  • Pair FlexTime with the first-node handling of your operation. Decide whether it allows early work or requires waiting, and set the early-arrival setting of the nodes to match.
  • Expect plans that are easier to accept. With StartReductionTime, the first stops align to their opening times, so the route timelines look more intuitive. This answers the question "why does every route start with a long drive?"

Properties

JOptWeight.TimeWindow.FlexTimePenalizeFactor penalizes used FlexTime, so that the optimizer starts routes close to the official start of the working hours. Its default and its allowed values are on Optimization properties.

Limits

FlexTime is hard constrained. If the configured maximum is 1 hour but the idle gap is 90 minutes, only 1 hour of delay is applied, and the remaining 30 minutes stay idle time. The optimizer never exceeds the allowed range. In the same way, a StartReductionTime that is too short does not reach the first node at its opening (Bob in Figure 3).

Authors

DNA Evolutions GmbH


Added: 2026-03-29 (JOpt core 7.5.3-j17) | Last updated: 2026-10-23