Timezones and Daylight Saving Time (DST)

The Employee Scheduling model supports multiple timezones and DST by accepting all date time attributes in the ISO 8601 local date time with an offset to UTC format, for example:

  • 2024-03-01T08:00:00 in London corresponds to the UTC timezone offset and becomes 2024-03-01T08:00:00Z (Z standing for UTC+0 offset),

  • 2024-03-01T08:00:00 in Atlanta corresponds to the UTC-4 timezone offset and becomes 2024-03-01T08:00:00-04.

Let’s start with DST change handling.

1. Daylight Saving Time (DST)

Since the model accepts all date times as a local date time with an offset to UTC, the client has full control over specifying how to cope with an extra hour, or a missing hour, during a DST change:

Imagine Carl has an overnight shift in Atlanta from 22:00 to 06:00 during the DST change to summer time. At 02:00 local time, the clock jumps 1 hour forward to 03:00. As a result, Carl’s shift will be 1 hour shorter if he finishes at his usual finish time of 06:00, alternatively, if Carl finishes at 07:00 instead of 06:00 his shift will still have a duration of 8 hours.

You can specify both scenarios by using the appropriate offset when defining the shift start and end. For instance:

  • After the DST change to winter time in Atlanta, the offset changes from -4 to -5.

  • After the DST change to summer time in Atlanta, the offset changes from -5 to -4.

  • Keep duration

  • Keep end local time

Keep shift duration, finish at 07:00 local time:

{
   "shifts": [
       {
        "id": "Carl's shift",
        "start": "2024-03-09T22:00:00-5",
        "end": "2024-03-10T07:00:00-4"
       }
   ]
}

Keep shift end at 06:00 local time, shorten the shift by one hour:

{
   "shifts": [
       {
        "id": "Carl's shift",
        "start": "2024-03-09T22:00:00-5",
        "end": "2024-03-10T06:00:00-4"
       }
   ]
}

When DST changes for winter time, a similar situation occurs. This time at 03:00 the clock goes back 1 hour. The duration of Carl’s shift will be 1 hour longer if he finishes at his usual finish time of 06:00, alternatively, if Carl finishes at 05:00 the shift will still have a duration of 8 hours.

  • Keep duration

  • Keep end local time

Keep shift duration, finish at 05:00 local time:

{
   "shifts": [
       {
        "id": "Carl's shift",
        "start": "2024-11-02T22:00:00-4",
        "end": "2024-11-03T05:00:00-5"
       }
   ]
}

Keep shift end at 06:00 local time, prolong the shift by one hour:

{
   "shifts": [
       {
        "id": "Carl's shift",
        "start": "2024-11-02T22:00:00-4",
        "end": "2024-11-03T06:00:00-5"
       }
   ]
}

In the following sections, let’s look at how specific rule types behave when matching shifts within multiple timezones against a specified time period.

2. Employee Period Rule and timezones

Let’s look at a specific example:

It takes 8 minutes to drive from Ranburne (Alabama) to Bowdon (Georgia), but these towns are in different timezones: Ranburn in Central Time (CT) and Bowdon in Eastern Time (ET).

Meet Beth, she is based in Ranburne, her home timezone offset is UTC-6 (Central Time during winter time):

  • Beth is assigned to Shift A in Ranburne from 2024-02-04T23:00:00-6 to 2024-02-05T06:00:00-6.

  • Next, she is assigned to Shift B in Bowdon, that is UTC-5 (Eastern Time in winter), starting at midnight local time (2024-02-06T00:00:00-5). That means 2024-02-05T23:00:00-6 Beth’s time.

  • Beth’s contract states that she is supposed to work at least 7 hours per day:

{
    "contracts": [
      {
        "id": "Beth's Contract",
        "periodRules": [
          {
             "id": "Min7HoursPerDay",
             "period": "DAY",
             "minutesWorkedMin": 420
          }
        ]
      }
    ],
    "employees": [
      {
        "id": "Beth",
        "contracts": [
          "Beth's Contract"
        ],
        "zoneOffset": "-06:00"
      }
    ]
}
The default value for the zoneOffset attribute is "Z" for UTC+0.

Had the Bowdon shift start time only been matched with Bowdon local date time, the rule would have prevented the above shift assignment to Beth because it would cause a contract violation.

employee period rule tz utc

3. Costs Rule and timezones

Let’s assume our schedule operates with shifts from two different sites, Atlanta (represented by the UTC-4 offset during winter time) and London (UTC+0, also denoted as Z):

  • On Monday 2024-02-05 midnight, London time, a new global feature will be rolled out, and the costs of both sites' shift assignments are expected to go higher than usual for the whole day.

  • A global costs rule is set up to define increased costs for this time period:

{
   "globalRules": {
    "costsRules": [
      {
         "id": "IncreasedCostsDuringRollout",
         "period": "rollout-day",
         "totalCostsMax": 10000,
         "zoneOffset": "Z"
      }
    ]
  }
}
The default value for the zoneOffset attribute is "Z" for UTC+0.
  • Suppose Shift A starts at 2024-02-04T20:00:00-4. It will be matched correctly by the rule because the rule converts the time to UTC+0 resulting in 2024-02-05T00:00:00Z.

  • Similarly, Shift B is starting at 2024-02-05T20:00:00-4. As expected, it will not be matched by the rule because the rule converts the time to UTC+0 resulting in 2024-02-06T00:00:00Z.

Had the shift start times been matched only as local date times, the rule would have matched shifts that are in fact outside the roll-out window.

costs rule tz utc

4. Global Period Rule and timezones

A Global Period Rule is capable of two different types of matching behavior, with or without taking the zone offset into account.

4.1. Global Period Rule with a specified zone offset

The first mode of operation takes the zone offset into account and is activated by specifying the zone offset in the rule definition (see the example below).

An example use-case is similar to the Costs Rule described above. Let’s assume that our schedule operates with shifts from two different sites, Atlanta (represented by the UTC-4 offset during winter time) and London (UTC+0):

  • On Monday 2024-02-05 midnight, London time, a new global feature will be rolled out, and the costs of both sites' shift assignments are expected to go higher than usual for the whole day.

  • A global period rule is set up to define the minimum and maximum number of shifts worked for this time period:

{
   "globalRules": {
    "minimumMaximumShiftsPerPeriod": [
      {
         "id": "IncreasedNumberOfShiftsDuringRollout",
         "period": "rollout-day",
         "shiftsWorkedMin": 20,
         "shiftsWorkedMax": 30,
         "zoneOffset": "Z"
      }
    ]
  }
}
The default value for the zoneOffset attribute in this rule is null, meaning the rule will assume the local date time mode of operation (see below)!
  • Suppose Shift A starts at 2024-02-04T20:00:00-4. It will be matched correctly by the rule because the rule converts the time to UTC+0 resulting in 2024-02-05T00:00:00Z.

  • Similarly, Shift B starts at 2024-02-05T20:00:00-4. As expected, it will not be matched by the rule because the rule converts the time to UTC+0 resulting in 2024-02-06T00:00:00Z.

global period rule tz utc

This mode of Global Period Rule operation is useful when multiple timezones need to synchronize on the same period on the timeline. You can imagine it as all relevant date times being converted into a time instant (the number of milliseconds from the start of the epoch) and then compared.

4.2. Global Period Rule with an unspecified zone offset

The second mode of operation matches the shifts based on the local date time only and is activated by not specifying the zone offset in the rule definition:

Again, let’s assume that our schedule operates with shifts from two different sites, Atlanta (represented by the UTC-4 offset during winter time) and London (UTC+0):

  • The company declares Monday 2024-02-05 as a day off for all its sites. Monday 2024-02-05 starts and ends at a different point on the global timeline for each timezone.

  • A global period rule with an unspecified zone offset is used to set the maximum number of shifts worked that day to zero:

{
   "globalRules": {
    "minimumMaximumShiftsPerPeriod": [
      {
         "id": "IncreasedNumberOfShiftsDuringRollout",
         "period": "rollout-day",
         "shiftsWorkedMin": 0,
         "shiftsWorkedMax": 0,
         "zoneOffset": null
      }
    ]
  }
}
The default value for the zoneOffset attribute is null, therefore the attribute can be omitted completely.
  • Suppose Shift A starts at 2024-02-04T20:00:00-4. This time, it will not be matched by the rule because the rule uses only the local date time part 2024-02-04T20:00:00 during matching.

  • Similarly, Shift B starts at 2024-02-05T20:00:00-4. As expected, it will be matched by the rule because the rule compares only the local date time part 2024-02-05T20:00:00.

global period rule tz local

This mode of Global Period Rule operation is useful when the rule needs to match shifts in time periods local to each shift timezone. You can imagine it as the zone offset information being removed from all relevant date times.