DateTimeRange
Generates a pair of date and time values, a start and an end, where the end is a set number of hours
after the start.
Use it for a row that represents a span of time, such as a shift, a call, a meeting, a session or an
outage. Two separate DateTime fields produce two unrelated values, and the second can
be earlier than the first. A DateTimeRange field always produces an end on or after its start.
Sub-fields: start and end. Both must be mapped. See Sub-fields.
Every JSON block on this page is a single field object, one entry in a table's fields array.
See Building a Request for the full request structure.
Sub-fields
| Sub-field | Example value | Description |
|---|---|---|
end |
2024-03-11 17:45:00 |
The end of the span, a number of hours after start set by the interval properties. Never earlier than start. |
start |
2024-03-11 09:15:00 |
The start of the span. |
Properties
The interval properties set the number of hours from the start to the end. The other properties apply
to the start, and have the same meaning as on a DateTime field. See
The interval.
| Property | Type | Default | Description |
|---|---|---|---|
cultureLong |
string? |
none | A culture name whose long date and time format is used for both values, with seconds. en-US produces 3/15/2024 1:05:00 PM. Produces text. Cannot be combined with exactFormat or cultureShort. |
cultureShort |
string? |
none | A culture name whose short date and time format is used for both values, without seconds. en-US produces 3/15/2024 1:05 PM. Produces text. Cannot be combined with exactFormat or cultureLong. |
exactFormat |
string? |
none | A custom date and time format string, used for both values. Produces text. Cannot be combined with cultureShort or cultureLong. |
intervalMax |
number? |
none | The largest number of hours from the start to the end. Required unless intervalMean is set. |
intervalMean |
number? |
none | The center of a normal distribution of interval lengths, in hours. Requires intervalStdDev. Cannot be combined with intervalPercentInRange. |
intervalMin |
number? |
0 |
The smallest number of hours from the start to the end. Must not be negative. |
intervalPercentInRange |
number? |
none | Percentage (0-100) of rows whose interval is generated from intervalPercentMin to intervalPercentMax. Cannot be combined with intervalMean. |
intervalPercentMax |
number? |
none | The upper bound of the narrower interval window, in hours. Required with intervalPercentInRange, and must be within intervalMin to intervalMax. |
intervalPercentMin |
number? |
none | The lower bound of the narrower interval window, in hours. Required with intervalPercentInRange, and must be within intervalMin to intervalMax. |
intervalStdDev |
number? |
none | The standard deviation of a normal distribution of interval lengths, in hours. Required with intervalMean, and must be greater than 0. |
lookupValues |
LookupValue[] |
none | The start values for Lookup mode. |
map |
object |
required | Maps start and end to destination columns. See Sub-fields and Building a Request. |
max |
string? (date-time) |
9999-12-31T23:59:59 |
Inclusive upper bound for the whole span, so the end is also on or before it. Random and Clustered only. |
mean |
string? (date-time) |
none | The center of the distribution of starts in Clustered mode. Required in that mode, with stdDev. |
min |
string? (date-time) |
0001-01-01T00:00:00 |
Inclusive lower bound for the start. Random and Clustered only. |
mode |
"Sequential" / "Random" / "Lookup" / "Clustered" |
"Sequential" |
How starts are generated. See Modes. |
nullPercentageMax |
number |
0 |
Upper bound (0-100) of the percentage of rows that should be null. See nullPercentageMin. |
nullPercentageMin |
number |
0 |
Lower bound (0-100) of the percentage of rows that should be null. The rate is fixed once for the whole field from this range, not recalculated per row. Set equal to nullPercentageMax for an exact rate. Has no effect in Sequential mode. |
percentInRange |
number? |
none | Percentage (0-100) of starts generated from percentMin to percentMax instead of the full range. Random only, and rejected in any other mode. See Random within a narrower window. |
percentMax |
string? (date-time) |
none | Upper bound of the window percentInRange applies to. Required with percentInRange. |
percentMin |
string? (date-time) |
none | Lower bound of the window percentInRange applies to. Required with percentInRange. |
seed |
integer |
random | Per-field seed, overriding the request's own seed for this field only. |
start |
string? (date-time) |
0001-01-01T00:00:00 |
The first row's start. Sequential only. |
stdDev |
number? |
none | The standard deviation of the distribution of starts in Clustered mode, in seconds. Required in that mode, with mean. |
stepDays |
number? |
see Stepping | Days added to each row's start in Sequential mode. |
stepHours |
number? |
see Stepping | Hours added to each row's start in Sequential mode. |
stepMinutes |
number? |
see Stepping | Minutes added to each row's start in Sequential mode. |
stepSeconds |
number? |
see Stepping | Seconds added to each row's start in Sequential mode. |
timeMax |
string? (time) |
23:59:59.9999999 |
Inclusive end of the time-of-day window for the start. Earlier than timeMin means the window continues through midnight. Random only, and rejected in any other mode. See The separate time of day. |
timeMean |
string? (time) |
none | The center of the time-of-day distribution for the start. Required with timeStdDev. Random only, and rejected in any other mode. |
timeMin |
string? (time) |
00:00:00 |
Inclusive start of the time-of-day window for the start. Later than timeMax means the window continues through midnight. Random only, and rejected in any other mode. See The separate time of day. |
timePercentInRange |
number? |
none | Percentage (0-100) of start times generated from timePercentMin to timePercentMax. Cannot be combined with timeMean and timeStdDev. Random only, and rejected in any other mode. |
timePercentMax |
string? (time) |
none | Upper bound of the narrower time-of-day window. Required with timePercentInRange. Random only, and rejected in any other mode. |
timePercentMin |
string? (time) |
none | Lower bound of the narrower time-of-day window. Required with timePercentInRange. Random only, and rejected in any other mode. |
timeStdDev |
number? |
none | The standard deviation of the time-of-day distribution, in seconds. Required with timeMean, and must be greater than 0. Random only, and rejected in any other mode. |
unique |
boolean |
false |
Whether every generated pair must differ from the others. See Unique spans. |
weekDays |
string[]? |
every day | The days of the week the start can be on. The end can be on any day. Rejected in Lookup mode. |
Modes
The mode sets how each row's start is generated. The interval is generated separately for each row, in every mode.
Sequentialincreases by a fixed step. The first span starts atstart, and each later span starts one combined step ofstepDays,stepHours,stepMinutesandstepSecondsafter the one before. The starts are the same on every run, with or without aseed. The interval is still generated for each row.Randomgenerates each start independently, with every whole second frommintomaxequally likely.percentInRangeconcentrates a percentage of the starts in a narrower window.Lookupselects each start fromlookupValues, optionally weighted. It never produces a start that is not in the list.Clusteredgenerates starts in a normal distribution aroundmean, withstdDevsetting its width in seconds.
Properties by mode
A property that applies only to another mode is ignored, except percentInRange and the time
properties, which are rejected outside Random, and weekDays, which is rejected in Lookup.
| Property | Sequential | Random | Lookup | Clustered |
|---|---|---|---|---|
start, stepDays, stepHours, stepMinutes, stepSeconds |
Yes | |||
min, max |
Yes | Yes | ||
percentInRange, percentMin, percentMax |
Yes | |||
lookupValues |
Yes | |||
mean, stdDev |
Yes | |||
weekDays |
Yes | Yes | Yes | |
timeMin, timeMax |
Yes | |||
timeMean, timeStdDev |
Yes | |||
timePercentInRange, timePercentMin, timePercentMax |
Yes | |||
exactFormat, cultureShort, cultureLong |
Yes | Yes | Yes | Yes |
nullPercentageMin, nullPercentageMax |
Yes | Yes | Yes | |
intervalMin, intervalMax |
Yes | Yes | Yes | Yes |
intervalMean, intervalStdDev |
Yes | Yes | Yes | Yes |
intervalPercentInRange, intervalPercentMin, intervalPercentMax |
Yes | Yes | Yes | Yes |
Sequential mode never produces nulls. In every other mode, start and end are null on the same
rows, so a row never has a start without an end.
In Random and Clustered modes, a start on a day excluded by weekDays is generated again, and a
range with no allowed day in it is rejected. weekDays is rejected in Lookup mode, because every
start is written exactly as listed.
Each mode checks its own settings before any row is generated, so a missing mean or an empty
lookupValues list is rejected immediately.
The interval
The interval is the number of hours from the start to the end. Fractional hours are accepted, so 0.5
is thirty minutes and 7.5 is seven and a half hours. Both values are written to the second, so an
interval shorter than a second can produce an end equal to its start.
A field with neither intervalMax nor intervalMean is rejected.
With intervalMax and no intervalMean, every length from intervalMin to intervalMax is equally
likely. With intervalMean and intervalStdDev, the lengths follow a normal distribution. A length
below intervalMin, or above intervalMax where it is set, is set to that bound, so an end is never
earlier than its start.
Staying inside the bounds
In Random and Clustered modes, the whole span is within min to max, not just the start. A start
is never later than max less intervalMin. When the end of a span would still be after max, a new
start is generated until the span fits.
The interval is generated once for each row and kept while a new start is generated, so a span is never shortened to fit. Only its position changes.
An intervalMin longer than the whole range from min to max is rejected before any data is
generated.
Sequential and Lookup modes do not use min and max, so their spans can end after max.
Spans that cross midnight
An end can be on the day after its start, and outside the start's time-of-day window. The time-of-day properties apply to the start only. A night shift that starts between 22:00 and 23:00 and lasts about eight hours ends the next morning:
{
"type": "DateTimeRange",
"mode": "Random",
"min": "2024-01-01",
"max": "2024-02-01",
"timeMin": "22:00:00",
"timeMax": "23:00:00",
"intervalMin": 7.5,
"intervalMax": 8.5,
"map": {
"start": { "column": "shift_start", "dataType": "DateTime" },
"end": { "column": "shift_end", "dataType": "DateTime" }
}
}
Sample output:
| shift_start | shift_end |
|---|---|
| 2024-01-23 22:34:36 | 2024-01-24 07:02:37 |
| 2024-01-24 22:29:16 | 2024-01-25 06:11:49 |
| 2024-01-03 22:42:32 | 2024-01-04 07:07:56 |
| 2024-01-24 22:23:57 | 2024-01-25 06:41:04 |
| 2024-01-25 22:09:04 | 2024-01-26 05:43:09 |
| 2024-01-05 22:30:43 | 2024-01-06 06:29:59 |
max is February 1 rather than January 31, so that a shift starting on the evening of January 31 can
end the next morning within the range.
Unique spans
With unique set, every row has a different pair of values. The interval is a number of hours with a
fractional part, so pairs only have a fixed limit when intervalMin and intervalMax are the same.
Every pair then has the same length, and the limit is the number of distinct starts, counted as for a
DateTime field with max reduced by the length. A request for more
rows than that is rejected before any data is generated, stating how many are available.
When the length varies, there is no fixed limit, and a request that runs out of distinct pairs is rejected during generation.
Examples
A support call of a few minutes
{
"type": "DateTimeRange",
"mode": "Random",
"min": "2024-06-01",
"max": "2024-06-30",
"timeMin": "08:00:00",
"timeMax": "18:00:00",
"intervalMin": 0.05,
"intervalMax": 0.75,
"map": {
"start": { "column": "call_start", "dataType": "DateTime" },
"end": { "column": "call_end", "dataType": "DateTime" }
}
}
Sample output:
| call_start | call_end |
|---|---|
| 2024-06-05 11:03:38 | 2024-06-05 11:43:36 |
| 2024-06-27 17:06:50 | 2024-06-27 17:23:38 |
| 2024-06-06 15:49:09 | 2024-06-06 16:24:30 |
| 2024-06-17 11:25:03 | 2024-06-17 11:34:33 |
| 2024-06-28 12:06:02 | 2024-06-28 12:34:09 |
| 2024-06-25 09:59:12 | 2024-06-25 10:23:07 |
Every call is from 3 to 45 minutes long.
A working day of about seven and a half hours
With an intervalMean of 7.5 and an intervalStdDev of 1.25, about 95% of days are from 5 to 10 hours
long. intervalMin sets the shortest day to 4 hours.
{
"type": "DateTimeRange",
"mode": "Random",
"min": "2024-01-01",
"max": "2024-03-31",
"weekDays": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
"timeMin": "08:00:00",
"timeMax": "09:30:00",
"intervalMin": 4,
"intervalMean": 7.5,
"intervalStdDev": 1.25,
"map": {
"start": { "column": "clock_in", "dataType": "DateTime" },
"end": { "column": "clock_out", "dataType": "DateTime" }
}
}
Sample output:
| clock_in | clock_out |
|---|---|
| 2024-03-22 09:11:24 | 2024-03-22 17:17:24 |
| 2024-01-12 09:02:11 | 2024-01-12 18:29:24 |
| 2024-01-17 09:03:38 | 2024-01-17 15:47:04 |
| 2024-02-05 08:05:06 | 2024-02-05 14:03:47 |
| 2024-02-08 09:18:39 | 2024-02-08 16:41:50 |
| 2024-03-08 08:45:03 | 2024-03-08 16:50:57 |
Mostly short outages, with some longer ones
intervalPercentInRange generates a percentage of the lengths from a narrower window, and the rest from
the full range from intervalMin to intervalMax.
The rest are generated from the full range, which includes the window, so the proportion of lengths in
the window is slightly higher than intervalPercentInRange.
{
"type": "DateTimeRange",
"mode": "Random",
"min": "2024-01-01",
"max": "2024-12-31",
"intervalMin": 0.1,
"intervalMax": 48,
"intervalPercentInRange": 85,
"intervalPercentMin": 0.1,
"intervalPercentMax": 2,
"map": {
"start": { "column": "outage_start", "dataType": "DateTime" },
"end": { "column": "outage_end", "dataType": "DateTime" }
}
}
Sample output:
| outage_start | outage_end |
|---|---|
| 2024-10-08 00:15:03 | 2024-10-08 00:38:56 |
| 2024-06-27 03:24:16 | 2024-06-27 05:04:03 |
| 2024-05-05 15:33:53 | 2024-05-05 16:22:12 |
| 2024-06-09 16:15:10 | 2024-06-09 17:52:16 |
| 2024-10-28 08:48:50 | 2024-10-30 05:30:32 |
| 2024-10-01 19:24:23 | 2024-10-01 21:00:50 |
Five of the outages are under two hours, and one is about 45 hours.
A job at the same time each day
Sequential starts at start and moves forward by stepHours. A step of 24 hours keeps the same time
of day on each date. With intervalMin and intervalMax both set to 7.5, every run is seven and a half
hours long.
{
"type": "DateTimeRange",
"mode": "Sequential",
"start": "2024-03-01T08:00:00",
"stepHours": 24,
"intervalMin": 7.5,
"intervalMax": 7.5,
"map": {
"start": { "column": "run_start", "dataType": "DateTime" },
"end": { "column": "run_end", "dataType": "DateTime" }
}
}
Sample output:
| run_start | run_end |
|---|---|
| 2024-03-01 08:00:00 | 2024-03-01 15:30:00 |
| 2024-03-02 08:00:00 | 2024-03-02 15:30:00 |
| 2024-03-03 08:00:00 | 2024-03-03 15:30:00 |
| 2024-03-04 08:00:00 | 2024-03-04 15:30:00 |
| 2024-03-05 08:00:00 | 2024-03-05 15:30:00 |
| 2024-03-06 08:00:00 | 2024-03-06 15:30:00 |
Bookings from a fixed set of slots
Lookup selects each start from lookupValues. The interval is from half an hour to an hour and a half,
so two bookings with the same start can have different ends.
{
"type": "DateTimeRange",
"mode": "Lookup",
"lookupValues": [
{ "value": "2024-03-01T09:00:00", "weight": 2 },
{ "value": "2024-03-01T13:00:00" },
{ "value": "2024-03-02T09:00:00" }
],
"intervalMin": 0.5,
"intervalMax": 1.5,
"map": {
"start": { "column": "booked_from", "dataType": "DateTime" },
"end": { "column": "booked_to", "dataType": "DateTime" }
}
}
Sample output:
| booked_from | booked_to |
|---|---|
| 2024-03-02 09:00:00 | 2024-03-02 09:55:39 |
| 2024-03-02 09:00:00 | 2024-03-02 09:38:31 |
| 2024-03-01 09:00:00 | 2024-03-01 09:53:03 |
| 2024-03-01 09:00:00 | 2024-03-01 09:37:30 |
| 2024-03-01 09:00:00 | 2024-03-01 10:22:42 |
| 2024-03-01 13:00:00 | 2024-03-01 13:43:43 |
Calls clustered around mid-afternoon
Clustered generates most starts near mean. stdDev is in seconds, so 5400 is an hour and a half.
{
"type": "DateTimeRange",
"mode": "Clustered",
"mean": "2024-03-01T14:00:00",
"stdDev": 5400,
"min": "2024-03-01T06:00:00",
"max": "2024-03-01T22:00:00",
"intervalMin": 1,
"intervalMax": 3,
"map": {
"start": { "column": "call_start", "dataType": "DateTime" },
"end": { "column": "call_end", "dataType": "DateTime" }
}
}
Sample output:
| call_start | call_end |
|---|---|
| 2024-03-01 11:12:30 | 2024-03-01 12:45:16 |
| 2024-03-01 12:19:19 | 2024-03-01 14:04:09 |
| 2024-03-01 13:09:28 | 2024-03-01 15:48:24 |
| 2024-03-01 12:33:42 | 2024-03-01 14:11:08 |
| 2024-03-01 15:06:05 | 2024-03-01 16:55:40 |
| 2024-03-01 14:53:58 | 2024-03-01 16:07:24 |
stdDev applies to the start and is in seconds. intervalMin and intervalMax set the length and are
in hours.