GuidesAPI Reference
Guides

Limit maximum shift time

Introducing the maximum shift time limit for vehicles in your fleet promotes driver well-being, reduces the risk of accidents due to fatigue, and ensures compliance with legal regulations, especially in cases when the shift time (fleet.types.shifts) specified for the fleet surpasses the allowable duration due to possible fluctuations in workload or such operational needs as peak periods or busy seasons.

Understand the maximum shift time configuration

Within the HERE Tour Planning API, you can use the shiftTime object found within the fleet.types.limits configuration. This allows you to specify the maximum duration of a shift for each vehicle (in seconds), regardless of the overall duration of shifts for the fleet as determined by the start and end times of shifts (shifts.start.time and shifts.end.time).

Use case: Enforcing driver work hour limits for legal compliance

For example, consider a use case where the initially scheduled shift time for a fleet spans from 8 AM to 11 PM, totaling 15 hours, which exceeds the maximum driver work time of 8 hours. By implementing the maximum shift time, you ensure that while the entire fleet operates within the 15-hour shift time bounds, the optimization algorithm schedules tours to prevent each individual vehicle from working more than 8 hours.

The following simplified snippet shows the fleet.types.shifts and fleet.types.limits.shiftTime configuration, as described in the previous use case:

{
  "fleet": {
    "traffic": "historicalOnly",
    "types": [
      {
        "id": "Vehicle_1",
        "profile": "car",
        "costs": {...},
        "shifts": [ // Shift time that defines fleet-level working hours
          {
            "start": {
              "time": "2021-10-23T08:00:00Z",
              "location": {
                "lat": 51.059188,
                "lng": 13.540317
              }
            },
            "end": {
              "time": "2021-10-23T23:00:00Z",
              "location": {
                "lat": 51.059188,
                "lng": 13.540317
              }
            }
          }
        ],
        "limits": {
          "shiftTime": 28800 // Maximum tour duration for individual vehicles
        },
        "capacity": [...],
        "amount": ...
      }
    ],
    "profiles": [...]
  }
}

For more information, see API Reference.

Problem

The following full problem JSON reflects the shift and maximum shift durations as previously mentioned in the sample use case, for a fleet consisting of two vehicles. The tour plan for that fleet consists of 11 pickup or delivery jobs.

Click to expand/collapse the sample JSON
{
  "fleet": {
    "traffic": "historicalOnly",
    "types": [
      {
        "id": "Vehicle_1",
        "profile": "car",
        "costs": {
          "fixed": 10,
          "distance": 0.001,
          "time": 0.002
        },
        "shifts": [
          {
            "start": {
              "time": "2021-10-23T08:00:00Z",
              "location": {
                "lat": 51.059188,
                "lng": 13.540317
              }
            },
            "end": {
              "time": "2021-10-23T23:00:00Z",
              "location": {
                "lat": 51.059188,
                "lng": 13.540317
              }
            }
          }
        ],
        "limits": {
          "shiftTime": 28800
        },
        "capacity": [
          10
        ],
        "amount": 2
      }
    ],
    "profiles": [
      {
        "type": "car",
        "name": "car"
      }
    ]
  },
  "plan": {
    "jobs": [
      {
        "id": "Job-1_D",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "location": {
                    "lat": 51.039189,
                    "lng": 13.63855
                  },
                  "duration": 2700
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job-2_P",
        "tasks": {
          "pickups": [
            {
              "places": [
                {
                  "location": {
                    "lat": 51.05238,
                    "lng": 13.74114
                  },
                  "duration": 2700
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job-3_P",
        "tasks": {
          "pickups": [
            {
              "places": [
                {
                  "location": {
                    "lat": 51.06099,
                    "lng": 13.75245
                  },
                  "duration": 2700
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job-4_D",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "location": {
                    "lat": 51.06866,
                    "lng": 13.77273
                  },
                  "duration": 2700
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job-5_P",
        "tasks": {
          "pickups": [
            {
              "places": [
                {
                  "location": {
                    "lat": 51.08511,
                    "lng": 13.76875
                  },
                  "duration": 2700
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job-6_P",
        "tasks": {
          "pickups": [
            {
              "places": [
                {
                  "location": {
                    "lat": 51.124507,
                    "lng": 13.792324
                  },
                  "duration": 2700
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job-7_D",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "location": {
                    "lat": 51.119731,
                    "lng": 13.76543
                  },
                  "duration": 2700
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job-8_P",
        "tasks": {
          "pickups": [
            {
              "places": [
                {
                  "location": {
                    "lat": 51.11716,
                    "lng": 13.73054
                  },
                  "duration": 2700
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job-9_D",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "location": {
                    "lat": 51.132473,
                    "lng": 13.643954
                  },
                  "duration": 2700
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job-10_D",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "location": {
                    "lat": 51.121718,
                    "lng": 13.631475
                  },
                  "duration": 2700
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job-11_D",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "location": {
                    "lat": 51.11169515690879,
                    "lng": 13.622580586403492
                  },
                  "duration": 2700
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job-12_D",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "location": {
                    "lat": 51.11169515690879,
                    "lng": 13.622580586403492
                  },
                  "duration": 2700
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      },
      {
        "id": "Job-13_D",
        "tasks": {
          "deliveries": [
            {
              "places": [
                {
                  "location": {
                    "lat": 51.11169515690879,
                    "lng": 13.622580586403492
                  },
                  "duration": 2700
                }
              ],
              "demand": [
                1
              ]
            }
          ]
        }
      }
    ]
  }
}

Solution

The solution to the problem demonstrates how setting the maximum shift time prevents tours for individual vehicles from exceeding 8 hours, while maintaining efficiency:

Click to expand/collapse the sample JSON
{
  "statistic": {
    "cost": 192.204,
    "distance": 88206,
    "duration": 41999,
    "times": {
      "driving": 6899,
      "serving": 35100,
      "waiting": 0,
      "stopping": 0,
      "break": 0
    }
  },
  "tours": [
    {
      "vehicleId": "Vehicle_1_1",
      "typeId": "Vehicle_1",
      "stops": [
        {
          "time": {
            "arrival": "2021-10-23T08:00:00Z",
            "departure": "2021-10-23T08:00:00Z"
          },
          "load": [
            3
          ],
          "activities": [
            {
              "jobId": "departure",
              "type": "departure",
              "location": {
                "lat": 51.059188,
                "lng": 13.540317
              },
              "time": {
                "start": "2021-10-23T08:00:00Z",
                "end": "2021-10-23T08:00:00Z"
              }
            }
          ],
          "location": {
            "lat": 51.059188,
            "lng": 13.540317
          },
          "distance": 0
        },
        {
          "time": {
            "arrival": "2021-10-23T08:16:03Z",
            "departure": "2021-10-23T09:01:03Z"
          },
          "load": [
            4
          ],
          "activities": [
            {
              "jobId": "Job-8_P",
              "type": "pickup",
              "location": {
                "lat": 51.11716,
                "lng": 13.73054
              },
              "time": {
                "start": "2021-10-23T08:16:03Z",
                "end": "2021-10-23T09:01:03Z"
              }
            }
          ],
          "location": {
            "lat": 51.11716,
            "lng": 13.73054
          },
          "distance": 19959
        },
        {
          "time": {
            "arrival": "2021-10-23T09:05:50Z",
            "departure": "2021-10-23T09:50:50Z"
          },
          "load": [
            3
          ],
          "activities": [
            {
              "jobId": "Job-7_D",
              "type": "delivery",
              "location": {
                "lat": 51.119731,
                "lng": 13.76543
              },
              "time": {
                "start": "2021-10-23T09:05:50Z",
                "end": "2021-10-23T09:50:50Z"
              }
            }
          ],
          "location": {
            "lat": 51.119731,
            "lng": 13.76543
          },
          "distance": 22945
        },
        {
          "time": {
            "arrival": "2021-10-23T09:54:19Z",
            "departure": "2021-10-23T10:39:19Z"
          },
          "load": [
            4
          ],
          "activities": [
            {
              "jobId": "Job-6_P",
              "type": "pickup",
              "location": {
                "lat": 51.124507,
                "lng": 13.792324
              },
              "time": {
                "start": "2021-10-23T09:54:19Z",
                "end": "2021-10-23T10:39:19Z"
              }
            }
          ],
          "location": {
            "lat": 51.124507,
            "lng": 13.792324
          },
          "distance": 25659
        },
        {
          "time": {
            "arrival": "2021-10-23T10:46:57Z",
            "departure": "2021-10-23T11:31:57Z"
          },
          "load": [
            5
          ],
          "activities": [
            {
              "jobId": "Job-5_P",
              "type": "pickup",
              "location": {
                "lat": 51.08511,
                "lng": 13.76875
              },
              "time": {
                "start": "2021-10-23T10:46:57Z",
                "end": "2021-10-23T11:31:57Z"
              }
            }
          ],
          "location": {
            "lat": 51.08511,
            "lng": 13.76875
          },
          "distance": 31008
        },
        {
          "time": {
            "arrival": "2021-10-23T11:37:38Z",
            "departure": "2021-10-23T12:22:38Z"
          },
          "load": [
            4
          ],
          "activities": [
            {
              "jobId": "Job-4_D",
              "type": "delivery",
              "location": {
                "lat": 51.06866,
                "lng": 13.77273
              },
              "time": {
                "start": "2021-10-23T11:37:38Z",
                "end": "2021-10-23T12:22:38Z"
              }
            }
          ],
          "location": {
            "lat": 51.06866,
            "lng": 13.77273
          },
          "distance": 34353
        },
        {
          "time": {
            "arrival": "2021-10-23T12:27:34Z",
            "departure": "2021-10-23T13:12:34Z"
          },
          "load": [
            5
          ],
          "activities": [
            {
              "jobId": "Job-3_P",
              "type": "pickup",
              "location": {
                "lat": 51.06099,
                "lng": 13.75245
              },
              "time": {
                "start": "2021-10-23T12:27:34Z",
                "end": "2021-10-23T13:12:34Z"
              }
            }
          ],
          "location": {
            "lat": 51.06099,
            "lng": 13.75245
          },
          "distance": 36514
        },
        {
          "time": {
            "arrival": "2021-10-23T13:18:16Z",
            "departure": "2021-10-23T14:03:16Z"
          },
          "load": [
            6
          ],
          "activities": [
            {
              "jobId": "Job-2_P",
              "type": "pickup",
              "location": {
                "lat": 51.05238,
                "lng": 13.74114
              },
              "time": {
                "start": "2021-10-23T13:18:16Z",
                "end": "2021-10-23T14:03:16Z"
              }
            }
          ],
          "location": {
            "lat": 51.05238,
            "lng": 13.74114
          },
          "distance": 38810
        },
        {
          "time": {
            "arrival": "2021-10-23T14:16:20Z",
            "departure": "2021-10-23T15:01:20Z"
          },
          "load": [
            5
          ],
          "activities": [
            {
              "jobId": "Job-1_D",
              "type": "delivery",
              "location": {
                "lat": 51.039189,
                "lng": 13.63855
              },
              "time": {
                "start": "2021-10-23T14:16:20Z",
                "end": "2021-10-23T15:01:20Z"
              }
            }
          ],
          "location": {
            "lat": 51.039189,
            "lng": 13.63855
          },
          "distance": 47723
        },
        {
          "time": {
            "arrival": "2021-10-23T15:12:13Z",
            "departure": "2021-10-23T15:12:13Z"
          },
          "load": [
            0
          ],
          "activities": [
            {
              "jobId": "arrival",
              "type": "arrival",
              "location": {
                "lat": 51.059188,
                "lng": 13.540317
              },
              "time": {
                "start": "2021-10-23T15:12:13Z",
                "end": "2021-10-23T15:12:13Z"
              }
            }
          ],
          "location": {
            "lat": 51.059188,
            "lng": 13.540317
          },
          "distance": 57066
        }
      ],
      "statistic": {
        "cost": 118.932,
        "distance": 57066,
        "duration": 25933,
        "times": {
          "driving": 4333,
          "serving": 21600,
          "waiting": 0,
          "stopping": 0,
          "break": 0
        }
      },
      "shiftIndex": 0
    },
    {
      "vehicleId": "Vehicle_1_2",
      "typeId": "Vehicle_1",
      "stops": [
        {
          "time": {
            "arrival": "2021-10-23T08:00:00Z",
            "departure": "2021-10-23T08:00:00Z"
          },
          "load": [
            5
          ],
          "activities": [
            {
              "jobId": "departure",
              "type": "departure",
              "location": {
                "lat": 51.059188,
                "lng": 13.540317
              },
              "time": {
                "start": "2021-10-23T08:00:00Z",
                "end": "2021-10-23T08:00:00Z"
              }
            }
          ],
          "location": {
            "lat": 51.059188,
            "lng": 13.540317
          },
          "distance": 0
        },
        {
          "time": {
            "arrival": "2021-10-23T08:15:24Z",
            "departure": "2021-10-23T10:30:24Z"
          },
          "load": [
            2
          ],
          "activities": [
            {
              "jobId": "Job-11_D",
              "type": "delivery",
              "location": {
                "lat": 51.11169515690879,
                "lng": 13.622580586403492
              },
              "time": {
                "start": "2021-10-23T08:15:24Z",
                "end": "2021-10-23T09:00:24Z"
              }
            },
            {
              "jobId": "Job-12_D",
              "type": "delivery",
              "location": {
                "lat": 51.11169515690879,
                "lng": 13.622580586403492
              },
              "time": {
                "start": "2021-10-23T09:00:24Z",
                "end": "2021-10-23T09:45:24Z"
              }
            },
            {
              "jobId": "Job-13_D",
              "type": "delivery",
              "location": {
                "lat": 51.11169515690879,
                "lng": 13.622580586403492
              },
              "time": {
                "start": "2021-10-23T09:45:24Z",
                "end": "2021-10-23T10:30:24Z"
              }
            }
          ],
          "location": {
            "lat": 51.11169515690879,
            "lng": 13.622580586403492
          },
          "distance": 11544
        },
        {
          "time": {
            "arrival": "2021-10-23T10:35:54Z",
            "departure": "2021-10-23T11:20:54Z"
          },
          "load": [
            1
          ],
          "activities": [
            {
              "jobId": "Job-9_D",
              "type": "delivery",
              "location": {
                "lat": 51.132473,
                "lng": 13.643954
              },
              "time": {
                "start": "2021-10-23T10:35:54Z",
                "end": "2021-10-23T11:20:54Z"
              }
            }
          ],
          "location": {
            "lat": 51.132473,
            "lng": 13.643954
          },
          "distance": 15411
        },
        {
          "time": {
            "arrival": "2021-10-23T11:23:14Z",
            "departure": "2021-10-23T12:08:14Z"
          },
          "load": [
            0
          ],
          "activities": [
            {
              "jobId": "Job-10_D",
              "type": "delivery",
              "location": {
                "lat": 51.121718,
                "lng": 13.631475
              },
              "time": {
                "start": "2021-10-23T11:23:14Z",
                "end": "2021-10-23T12:08:14Z"
              }
            }
          ],
          "location": {
            "lat": 51.121718,
            "lng": 13.631475
          },
          "distance": 17017
        },
        {
          "time": {
            "arrival": "2021-10-23T12:27:46Z",
            "departure": "2021-10-23T12:27:46Z"
          },
          "load": [
            0
          ],
          "activities": [
            {
              "jobId": "arrival",
              "type": "arrival",
              "location": {
                "lat": 51.059188,
                "lng": 13.540317
              },
              "time": {
                "start": "2021-10-23T12:27:46Z",
                "end": "2021-10-23T12:27:46Z"
              }
            }
          ],
          "location": {
            "lat": 51.059188,
            "lng": 13.540317
          },
          "distance": 31140
        }
      ],
      "statistic": {
        "cost": 73.27199999999999,
        "distance": 31140,
        "duration": 16066,
        "times": {
          "driving": 2566,
          "serving": 13500,
          "waiting": 0,
          "stopping": 0,
          "break": 0
        }
      },
      "shiftIndex": 0
    }
  ]
}

The following figure provides the solution visualization:

VRP solution with maximum shift time

As the solution demonstrates, for a shift starting at 8 AM and ending at 11 PM, the algorithm created two tours, ensuring that no vehicle extended the maximum shift time limit of 28800 seconds (8 hours), ensuring efficient distribution of workload and adherence to legal regulations regarding maximum working hours for drivers.

The following visualisation showcases a solution to the identical problem, except with the maximum shift time limit of 28800 seconds removed:

VRP solution without maximum shift time

In this case, the algorithm determined that the tour could be completed efficiently by just one vehicle. However, the tour took over 11 hours, exceeding the maximum driver working time.

Conclusions

Implementing a shift time cap for individual vehicles alongside the regular shift time facilitates better planning and optimization of the fleet's resources. Breaking the workload into manageable chunks simplifies task assignment while maintaining efficient vehicle allocation, adhering to legal requirements, and promoting driver well-being.

Next steps

  • For more information about formulating problems in the HERE Tour Planning API, see Problem.
  • For an in-depth exploration of the HERE Tour Planning API methods, endpoints, and parameters, see the API Reference.
  • To explore other limit types, see Set route limits.