FAILURE MAP
← Case archive

FA-94056 / Shift rostering labor rules / Open access

Weekend premium attributed by shift start day · case 01

A Friday night shift running into Saturday gets no weekend premium, and a Sunday night shift is paid weekend rates into Monday.

Verified by executionVariant 1 · 8 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The weekend check uses the day of the shift start for every minute.

VERIFIED REPAIR

Determine the weekday of each minute worked.

Unsuccessful approach: Using the shift end day just moves the error to the other side of midnight.

Case contract

Shift [start, end] in minutes from Monday 00:00 and a base rate in cents per hour. Each minute earns base * (100 + pct) / 6000 cents where pct is 10 for 15:00-23:00, 15 for 23:00-07:00, else 0; on Saturday and Sunday (days 5 and 6) pct is the larger of that value and 12 (differentials do not stack). The exact total is rounded half up to a cent once.

Why this case matters

Shift differential calculations are where roster data meets payroll; stacking and day attribution errors are common.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(shift, base):
    s, e = shift
    total = 0
    for t in range(s, e):
        day = (s // 1440) % 7
        m = t % 1440
        pct = 0
        if 900 <= m < 1380:
            pct = 10
        if m >= 1380 or m < 420:
            pct = 15
        if day >= 5:
            pct = max(pct, 12)
        total += base * (100 + pct)
    return (total + 3000) // 6000
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: weekend by shift start 1', [[7080, 7680], 90], 1028),
  ('regression variant: weekend by shift start 2', [[7080, 7800], 60], 820),
  ('partial repair guard 3', [[9600, 10320], 1999], 27166),
  ('boundary control 4', [[8580, 8700], 2000], 4600), ('boundary control 5', [[900, 960], 1800], 1980),
  ('normal control 6', [[2400, 2880], 60], 531), ('normal control 7', [[4200, 4680], 60], 549),
  ('normal control 8', [[1860, 2340], 1999], 15992)],
 [('regression: weekend by shift start 1', [[7140, 7860], 1999], 27346),
  ('regression variant: weekend by shift start 2', [[10020, 10740], 60], 792),
  ('partial repair guard 3', [[9480, 10200], 60], 812), ('boundary control 4', [[0, 3], 10], 1),
  ('boundary control 5', [[8580, 8700], 2000], 4600), ('normal control 6', [[1380, 2100], 60], 792),
  ('normal control 7', [[1860, 2580], 2000], 24800), ('normal control 8', [[1800, 2280], 2000], 16300)],
 [('regression: weekend by shift start 1', [[10020, 10740], 2150], 28380),
  ('partial repair guard 2', [[6660, 7380], 2150], 28810),
  ('boundary control 3', [[6600, 7260], 2000], 24200), ('boundary control 4', [[0, 3], 10], 1),
  ('normal control 5', [[360, 600], 60], 249), ('normal control 6', [[3240, 3300], 60], 69),
  ('normal control 7', [[9600, 10200], 2000], 22580), ('normal control 8', [[0, 720], 60], 783)],
 [('regression: weekend by shift start 1', [[7140, 7740], 90], 1030),
  ('regression variant: weekend by shift start 2', [[7116, 7716], 1999], 22853),
  ('partial repair guard 3', [[9540, 10140], 1800], 20268), ('boundary control 4', [[1320, 1500], 60], 204),
  ('boundary control 5', [[6600, 7260], 2000], 24200), ('normal control 6', [[360, 840], 90], 734),
  ('normal control 7', [[360, 420], 90], 104), ('normal control 8', [[4740, 5460], 2000], 24800)],
 [('regression: weekend by shift start 1', [[7140, 7860], 1800], 24624),
  ('regression variant: weekend by shift start 2', [[10020, 10740], 90], 1188),
  ('partial repair guard 3', [[7080, 7800], 60], 820), ('boundary control 4', [[480, 960], 1999], 16192),
  ('boundary control 5', [[1320, 1500], 60], 204), ('normal control 6', [[7140, 7740], 90], 1030),
  ('normal control 7', [[9600, 9660], 2000], 2240), ('normal control 8', [[10020, 10058], 2150], 1566)]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
regression: weekend by shift start 110171028Failed
regression variant: weekend by shift start 2798820Failed
partial repair guard 32716627166Passed
boundary control 446004600Passed
boundary control 519801980Passed
normal control 6531531Passed
normal control 7549549Passed
normal control 81599215992Passed

SHA-256 / c02602e3e5831f76f01dc4c25e14d0539c269b3fc279d912ba3e64c4d23e3115

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(shift, base):
    s, e = shift
    total = 0
    for t in range(s, e):
        day = (e // 1440) % 7
        m = t % 1440
        pct = 0
        if 900 <= m < 1380:
            pct = 10
        if m >= 1380 or m < 420:
            pct = 15
        if day >= 5:
            pct = max(pct, 12)
        total += base * (100 + pct)
    return (total + 3000) // 6000
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: weekend by shift start 1', [[7080, 7680], 90], 1028),
  ('regression variant: weekend by shift start 2', [[7080, 7800], 60], 820),
  ('partial repair guard 3', [[9600, 10320], 1999], 27166),
  ('boundary control 4', [[8580, 8700], 2000], 4600), ('boundary control 5', [[900, 960], 1800], 1980),
  ('normal control 6', [[2400, 2880], 60], 531), ('normal control 7', [[4200, 4680], 60], 549),
  ('normal control 8', [[1860, 2340], 1999], 15992)],
 [('regression: weekend by shift start 1', [[7140, 7860], 1999], 27346),
  ('regression variant: weekend by shift start 2', [[10020, 10740], 60], 792),
  ('partial repair guard 3', [[9480, 10200], 60], 812), ('boundary control 4', [[0, 3], 10], 1),
  ('boundary control 5', [[8580, 8700], 2000], 4600), ('normal control 6', [[1380, 2100], 60], 792),
  ('normal control 7', [[1860, 2580], 2000], 24800), ('normal control 8', [[1800, 2280], 2000], 16300)],
 [('regression: weekend by shift start 1', [[10020, 10740], 2150], 28380),
  ('partial repair guard 2', [[6660, 7380], 2150], 28810),
  ('boundary control 3', [[6600, 7260], 2000], 24200), ('boundary control 4', [[0, 3], 10], 1),
  ('normal control 5', [[360, 600], 60], 249), ('normal control 6', [[3240, 3300], 60], 69),
  ('normal control 7', [[9600, 10200], 2000], 22580), ('normal control 8', [[0, 720], 60], 783)],
 [('regression: weekend by shift start 1', [[7140, 7740], 90], 1030),
  ('regression variant: weekend by shift start 2', [[7116, 7716], 1999], 22853),
  ('partial repair guard 3', [[9540, 10140], 1800], 20268), ('boundary control 4', [[1320, 1500], 60], 204),
  ('boundary control 5', [[6600, 7260], 2000], 24200), ('normal control 6', [[360, 840], 90], 734),
  ('normal control 7', [[360, 420], 90], 104), ('normal control 8', [[4740, 5460], 2000], 24800)],
 [('regression: weekend by shift start 1', [[7140, 7860], 1800], 24624),
  ('regression variant: weekend by shift start 2', [[10020, 10740], 90], 1188),
  ('partial repair guard 3', [[7080, 7800], 60], 820), ('boundary control 4', [[480, 960], 1999], 16192),
  ('boundary control 5', [[1320, 1500], 60], 204), ('normal control 6', [[7140, 7740], 90], 1030),
  ('normal control 7', [[9600, 9660], 2000], 2240), ('normal control 8', [[10020, 10058], 2150], 1566)]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
regression: weekend by shift start 110301028Failed
regression variant: weekend by shift start 2821820Failed
partial repair guard 32688727166Failed
boundary control 446004600Passed
boundary control 519801980Passed
normal control 6531531Passed
normal control 7549549Passed
normal control 81599215992Passed

SHA-256 / 0ee42dd82af0066e597de510ac3fdd32ac69e7e6d7a9ef397e1a7e3cf611066a

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(shift, base):
    s, e = shift
    total = 0
    for t in range(s, e):
        day = (t // 1440) % 7
        m = t % 1440
        pct = 0
        if 900 <= m < 1380:
            pct = 10
        if m >= 1380 or m < 420:
            pct = 15
        if day >= 5:
            pct = max(pct, 12)
        total += base * (100 + pct)
    return (total + 3000) // 6000
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: weekend by shift start 1', [[7080, 7680], 90], 1028),
  ('regression variant: weekend by shift start 2', [[7080, 7800], 60], 820),
  ('partial repair guard 3', [[9600, 10320], 1999], 27166),
  ('boundary control 4', [[8580, 8700], 2000], 4600), ('boundary control 5', [[900, 960], 1800], 1980),
  ('normal control 6', [[2400, 2880], 60], 531), ('normal control 7', [[4200, 4680], 60], 549),
  ('normal control 8', [[1860, 2340], 1999], 15992)],
 [('regression: weekend by shift start 1', [[7140, 7860], 1999], 27346),
  ('regression variant: weekend by shift start 2', [[10020, 10740], 60], 792),
  ('partial repair guard 3', [[9480, 10200], 60], 812), ('boundary control 4', [[0, 3], 10], 1),
  ('boundary control 5', [[8580, 8700], 2000], 4600), ('normal control 6', [[1380, 2100], 60], 792),
  ('normal control 7', [[1860, 2580], 2000], 24800), ('normal control 8', [[1800, 2280], 2000], 16300)],
 [('regression: weekend by shift start 1', [[10020, 10740], 2150], 28380),
  ('partial repair guard 2', [[6660, 7380], 2150], 28810),
  ('boundary control 3', [[6600, 7260], 2000], 24200), ('boundary control 4', [[0, 3], 10], 1),
  ('normal control 5', [[360, 600], 60], 249), ('normal control 6', [[3240, 3300], 60], 69),
  ('normal control 7', [[9600, 10200], 2000], 22580), ('normal control 8', [[0, 720], 60], 783)],
 [('regression: weekend by shift start 1', [[7140, 7740], 90], 1030),
  ('regression variant: weekend by shift start 2', [[7116, 7716], 1999], 22853),
  ('partial repair guard 3', [[9540, 10140], 1800], 20268), ('boundary control 4', [[1320, 1500], 60], 204),
  ('boundary control 5', [[6600, 7260], 2000], 24200), ('normal control 6', [[360, 840], 90], 734),
  ('normal control 7', [[360, 420], 90], 104), ('normal control 8', [[4740, 5460], 2000], 24800)],
 [('regression: weekend by shift start 1', [[7140, 7860], 1800], 24624),
  ('regression variant: weekend by shift start 2', [[10020, 10740], 90], 1188),
  ('partial repair guard 3', [[7080, 7800], 60], 820), ('boundary control 4', [[480, 960], 1999], 16192),
  ('boundary control 5', [[1320, 1500], 60], 204), ('normal control 6', [[7140, 7740], 90], 1030),
  ('normal control 7', [[9600, 9660], 2000], 2240), ('normal control 8', [[10020, 10058], 2150], 1566)]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
regression: weekend by shift start 110281028Passed
regression variant: weekend by shift start 2820820Passed
partial repair guard 32716627166Passed
boundary control 446004600Passed
boundary control 519801980Passed
normal control 6531531Passed
normal control 7549549Passed
normal control 81599215992Passed

SHA-256 / 050a6f1922f3f88b226400f3f04fdd3273987c8c9e78be154f2e12cbc568c26d

Verification & scope

Stipulated toy labor rule for a bounded roster model; it is not legal advice and does not claim conformance with any jurisdiction, award, or collective agreement. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.

Observations recorded using Python 3.12.14 at 2026-09-29T14:52:00.754074+00:00.

Case digest / 5fe7015cc47ea6bf7e8043532ec8685153f4d250cd713fd46dfdeec97a89bb11