evaluateDutyLog
Signature
Section titled “Signature”evaluateDutyLog(log: DutyEntry[], at: string, rules: DutyRule[], options: { timeZone: string; dayStartTime?: string; disambiguation?: "compatible" | "earlier" | "later" | "reject" | undefined; }): DutyReport | nullEvaluate every hours-of-work rule over a duty log at one instant, and report each one whether or not it binds.
- GMT implements no regulation: each rule is a shape, and every number in it is the caller’s. A regime is the array of rules the caller assembles and labels. GMT reports totals, what is left and what failed; it does not decide dispatch, fitness or eligibility.
- The log is read as it stands at
at: later entries are ignored and one straddlingatis cut there. Time no entry covers is in no status, so it is neither work nor rest. That includes the time before the log’s first entry: give a log that reaches back as far as the longest rule looks, or a rest rule fails for want of logged rest. A planned roster is the same call with the plan appended andatset to its end. - This is the strict reading, for a check before dispatch.
dutyViolationsreads a record the other way: it does not judge a rest rule on a window that starts before the log’s first entry, since the log cannot say what happened then. Both read the log’s first entry as the start of a stretch without rest formaxGap, as the end of a rest would be. - Every outcome carries
used,limit,remaining,window,dueByandresetAt, so the second-tightest limit is visible before it binds. Failed rules are listed again underviolationsor, withseverity: "advisory", underadvisoriesonly. - A duration in a
Periodis a sliding window ending atat;operatorDaysare the days ofdutyDayFor; calendar days, ISO weeks, months and years are local periods intimeZone, 23 or 25 hours long across a one-hour clock change. Each outcome names itsperiodBasis. - The local periods are the ones holding the last instant before
at, so at a boundary the period just ended is judged: a roster ending at midnight is checked through its last day. - A window that runs past
at(the rest of today, this week) has not failed a minimum while the minimum could still be met with rest fromatto its end; a cap fails as soon as it is passed. - Endpoints are UTC instants ending in “Z”; durations are ISO 8601 with hours as the largest unit (
"PT49H30M"). - Returns
nullwhen the log failsisValidDutyLog, whenatis not an ISO 8601 instant string, when a rule is malformed (an unknown kind, a status list that is empty or holds a non-string, a duration that is not positive exact time, a malformed period, a duplicate label, a count of periods past 10,000 alone or timesadjacent,lookbackorperiods, acontaining.countpast 10,000), whenoptions.timeZoneis invalid, when a rule countsoperatorDayswithoutoptions.dayStartTime, when a window, or a requirementorFactorscales, falls outside Temporal’s range, when a count of free periods passesNumber.MAX_SAFE_INTEGER, and when one run of rest in afreePeriodwindow holds more than 20,000 of itscontainingwindows (about 54 years of a daily window).
Parameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
log | DutyEntry[] | the duty log, ordered and non-overlapping |
at | string | ISO 8601 instant string to evaluate at |
rules | DutyRule[] | the rules, every number the caller’s |
Options
Section titled “Options”options
the reference zone and the operator day
| Option | Type | Default | Description |
|---|---|---|---|
timeZone | string | Required | The reference time zone every local period is read in, an IANA name or UTC offset: a time zone identifier (+05:30, +0530, -08) or a stored offset (±HH:MM[:SS], what getTimeZoneOffset returns). A log kept in another clock is converted to instants first. |
dayStartTime? | string | None. A rule that counts operator days makes the call invalid. | The local wall time each operator day starts at, as an ISO PlainTime string ("04:00"). A rule that counts operatorDays needs it. |
disambiguation? | "compatible" | "earlier" | "later" | "reject" (Disambiguation) | "compatible", Temporal’s default. | How a day start, or a freePeriod window edge, that the clock repeats or skips becomes an instant, as resolveLocal resolves it. "compatible" reads a skipped time after the gap and a repeated one at its first pass, "earlier" and "later" take that side in both cases, and "reject" returns the sentinel when an operator day a rule counts starts or ends at such a time, or a local window with such an edge reaches a logged free period. |
Returns
Section titled “Returns”the report, or null on invalid input
DutyReport
Section titled “DutyReport”Every rule of a regime evaluated at one instant.
import type { DutyReport } from "@northguild/gmt";| Member | Type | Description |
|---|---|---|
at | string | The instant evaluated, as a UTC instant. |
outcomes | RuleOutcome[] (RuleOutcome) | One outcome per rule, in the order the rules were given. |
violations | RuleOutcome[] (RuleOutcome) | The outcomes of failed rules whose severity is "violation". |
advisories | RuleOutcome[] (RuleOutcome) | The outcomes of failed rules whose severity is "advisory". |
RuleOutcome
Section titled “RuleOutcome”One rule evaluated at one instant, reported whether or not it binds. Durations are ISO 8601 with hours as the largest unit; counts are numbers.
import type { RuleOutcome } from "@northguild/gmt";| Member | Type | Description |
|---|---|---|
label | string | The rule’s label. |
kind | "cumulativeCap" | "elapsedWindow" | "requiredInterruption" | "rollingCap" | "fixedPeriodCap" | "restRequirement" | "freePeriod" | "restBeforeDuty" | "quota" | "dueBy" | "pattern" | "occurrenceCap" | "usageLookback" (DutyRule) | The rule’s kind. |
severity | "violation" | "advisory" (DutySeverity) | The rule’s severity, "violation" when the rule gave none. |
satisfied | boolean | Whether the rule holds at the instant evaluated. |
used | string | number | null | How much the rule has used, or found: a duration or a count; null when nothing is measured. |
limit | string | number | null | The figure used is held to: a cap, a minimum or a count. |
remaining | string | number | null | What is left before a cap binds, or still needed to meet a minimum; never negative. |
window | Interval | null (Interval) | The span the rule measured, as UTC instants. A window of local periods runs to the end of the current period, past the instant evaluated. Null when the rule has not started: an elapsedWindow with no work since its reset. |
periodBasis | PeriodBasis | null (PeriodBasis) | How window was counted; null when the rule has no window of its own. |
dueBy | string | null | The instant something is due by: a window’s close, a rest’s deadline; null when none. |
resetAt | string | null | Where the last reset ended, as a UTC instant; null when the rule has none or none occurred. |
PeriodBasis
Section titled “PeriodBasis”Which arithmetic a window used: exact elapsed time, operator days, or local calendar periods.
import type { PeriodBasis } from "@northguild/gmt";"calendar" | "elapsed" | "operatorDay"Related types
Section titled “Related types”DutyEntryDutyRuleCumulativeCapRuleDutySeverityResetElapsedWindowRulePairSpecRequiredInterruptionRuleRollingCapRulePeriodElapsedPeriodOperatorDaysPeriodCalendarDaysPeriodIsoWeeksPeriodCalendarMonthsPeriodCalendarYearsPeriodFixedPeriodCapRuleLocalPeriodRestRequirementRuleFreePeriodRuleLocalWindowRestBeforeDutyRuleQuotaRuleDueByRulePatternRuleOccurrenceCapRuleUsageLookbackRuleDisambiguationInterval
Examples
Section titled “Examples”import { evaluateDutyLog } from "@northguild/gmt/duty/calculate";
evaluateDutyLog([{ status: "off", start: "2024-01-01T00:00:00Z", end: "2024-01-01T10:00:00Z" }, { status: "driving", start: "2024-01-01T10:00:00Z", end: "2024-01-01T21:00:00Z" }], "2024-01-01T21:00:00Z", [{ label: "11 driving", kind: "cumulativeCap", statuses: ["driving"], cap: "PT11H", since: { statuses: ["off"], consecutive: "PT10H" } }], { timeZone: "UTC" }) // { at: "2024-01-01T21:00:00Z", outcomes: [{ label: "11 driving", kind: "cumulativeCap", severity: "violation", satisfied: true, used: "PT11H", limit: "PT11H", remaining: "PT0S", window: { start: "2024-01-01T10:00:00Z", end: "2024-01-01T21:00:00Z" }, periodBasis: null, dueBy: null, resetAt: "2024-01-01T10:00:00Z" }], violations: [], advisories: [] }