FA-78211 / Subtitle cue timing / Open access
Timed-text time expression evaluation: clock rounding · case 01
Clock times with half-millisecond frames end up one millisecond early.
ROOT CAUSE
The exact clock value is truncated instead of rounded half up.
VERIFIED REPAIR
Round the exact clock value half up.
Unsuccessful approach: Round-half-even rounds some exact halves down.
Case contract
Evaluate a timed-text time expression to integer ms, rounded half up. Offset form <number><metric> with metric h, m, s, ms, f (frames at frame_rate) or t (ticks at tick_rate). Clock form HH:MM:SS with optional .fraction (any digits) or :FF frames (FF < frame_rate). Minutes/seconds above 59 or malformed text give None.
Why this case matters
Subtitle timing defects shift, hide or overlap captions that viewers depend on for comprehension and accessibility.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
import re
from fractions import Fraction
N = 1
observations = []
def solve(expr, frame_rate, tick_rate):
m=re.fullmatch(r'(\d+(?:\.\d+)?)(h|ms|m|s|f|t)',expr)
if m:
v=Fraction(m.group(1))
unit=m.group(2)
scale={'h':3600000,'m':60000,'s':1000,'ms':1}
if unit in scale:
x=v*scale[unit]
elif unit=='f':
x=v*1000/frame_rate
else:
x=v*1000/tick_rate
return math.floor(x+Fraction(1,2))
m=re.fullmatch(r'(\d{2,}):(\d{2}):(\d{2})(?:\.(\d+)|:(\d{2,}))?',expr)
if not m:
return None
h,mi,se,frac,fr=m.groups()
if int(mi)>59 or int(se)>59:
return None
x=Fraction(int(h)*3600+int(mi)*60+int(se))*1000
if frac:
x+=Fraction('0.'+frac)*1000
if fr:
if int(fr)>=frame_rate:
return None
x+=Fraction(int(fr)*1000,frame_rate)
return int(x)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: clock rounding', ['00:00:01:15', 16, 1000], 1938), ('regression variant: clock rounding', ['10:59:59.0005', 50, 90000], 39599001), ('partial repair probe: clock rounding', ['100:59:00.0005', 16, 3], 363540001), ('partial repair variant: clock rounding', ['10:30:00.0005', 24, 90000], 37800001), ('boundary control', ['10t', 25, 1000], 10), ('boundary control', ['3f', 16, 1000], 188), ('normal control', ['00:00:00:25', 25, 1000], None), ('normal control', ['10:59:59:15', 40, 1000], 39599375), ('normal control', ['15h', 50, 1000], 54000000)], [('regression: clock rounding', ['00:00:01.0005', 25, 1000], 1001), ('regression variant: clock rounding', ['10:59:59:29', 30, 90000], 39599967), ('partial repair probe: clock rounding', ['00:00:00:01', 16, 1000], 63), ('partial repair variant: clock rounding', ['100:59:59.0005', 40, 1000], 363599001), ('boundary control', ['3f', 16, 1000], 188), ('boundary control', ['00:00:00:25', 25, 1000], None), ('normal control', ['15m', 30, 1000], 900000), ('normal control', ['10:59:00:15', 40, 90000], 39540375), ('normal control', ['00:00:59:12', 30, 10000000], 59400)], [('regression: clock rounding', ['00:30:00:15', 16, 10000000], 1800938), ('regression variant: clock rounding', ['100:59:00.0005', 16, 3], 363540001), ('partial repair probe: clock rounding', ['100:30:59.0005', 40, 3], 361859001), ('partial repair variant: clock rounding', ['10:00:00.0005', 50, 3], 36000001), ('boundary control', ['00:00:00:25', 25, 1000], None), ('boundary control', ['10t', 25, 1000], 10), ('normal control', ['100:30:59:30', 25, 10000000], None), ('normal control', ['15t', 30, 3], 5000), ('normal control', ['01:60:05:12', 16, 10000000], None)], [('regression: clock rounding', ['00:30:00:01', 24, 1000], 1800042), ('regression variant: clock rounding', ['00:00:00:01', 16, 1000], 63), ('partial repair probe: clock rounding', ['01:30:05.0005', 30, 1000], 5405001), ('partial repair variant: clock rounding', ['10:30:05.0005', 30, 90000], 37805001), ('boundary control', ['10t', 25, 1000], 10), ('boundary control', ['3f', 16, 1000], 188), ('normal control', ['0t', 24, 3], 0), ('normal control', ['1.5t', 16, 3], 500), ('normal control', ['10:00:00.25', 16, 3], 36000250)], [('regression: clock rounding', ['01:59:59:01', 24, 3], 7199042), ('regression variant: clock rounding', ['100:30:00:15', 16, 90000], 361800938), ('partial repair probe: clock rounding', ['00:30:00.0005', 40, 3], 1800001), ('partial repair variant: clock rounding', ['00:59:00.0005', 24, 10000000], 3540001), ('boundary control', ['3f', 16, 1000], 188), ('boundary control', ['00:00:00:25', 25, 1000], None), ('normal control', ['10:30:59.5', 24, 1000], 37859500), ('normal control', ['01:30:05:25', 16, 90000], None), ('normal control', ['17h', 24, 10000000], 61200000)]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: clock rounding | 1937 | 1938 | Failed |
| regression variant: clock rounding | 39599000 | 39599001 | Failed |
| partial repair probe: clock rounding | 363540000 | 363540001 | Failed |
| partial repair variant: clock rounding | 37800000 | 37800001 | Failed |
| boundary control | 10 | 10 | Passed |
| boundary control | 188 | 188 | Passed |
| normal control | None | None | Passed |
| normal control | 39599375 | 39599375 | Passed |
| normal control | 54000000 | 54000000 | Passed |
SHA-256 / 592d73b83b103d937aa8fdf8ed6df909117f69ddd627e3a6acbf4b7d7718a9e7
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
import re
from fractions import Fraction
N = 1
observations = []
def solve(expr, frame_rate, tick_rate):
m=re.fullmatch(r'(\d+(?:\.\d+)?)(h|ms|m|s|f|t)',expr)
if m:
v=Fraction(m.group(1))
unit=m.group(2)
scale={'h':3600000,'m':60000,'s':1000,'ms':1}
if unit in scale:
x=v*scale[unit]
elif unit=='f':
x=v*1000/frame_rate
else:
x=v*1000/tick_rate
return math.floor(x+Fraction(1,2))
m=re.fullmatch(r'(\d{2,}):(\d{2}):(\d{2})(?:\.(\d+)|:(\d{2,}))?',expr)
if not m:
return None
h,mi,se,frac,fr=m.groups()
if int(mi)>59 or int(se)>59:
return None
x=Fraction(int(h)*3600+int(mi)*60+int(se))*1000
if frac:
x+=Fraction('0.'+frac)*1000
if fr:
if int(fr)>=frame_rate:
return None
x+=Fraction(int(fr)*1000,frame_rate)
return round(x)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: clock rounding', ['00:00:01:15', 16, 1000], 1938), ('regression variant: clock rounding', ['10:59:59.0005', 50, 90000], 39599001), ('partial repair probe: clock rounding', ['100:59:00.0005', 16, 3], 363540001), ('partial repair variant: clock rounding', ['10:30:00.0005', 24, 90000], 37800001), ('boundary control', ['10t', 25, 1000], 10), ('boundary control', ['3f', 16, 1000], 188), ('normal control', ['00:00:00:25', 25, 1000], None), ('normal control', ['10:59:59:15', 40, 1000], 39599375), ('normal control', ['15h', 50, 1000], 54000000)], [('regression: clock rounding', ['00:00:01.0005', 25, 1000], 1001), ('regression variant: clock rounding', ['10:59:59:29', 30, 90000], 39599967), ('partial repair probe: clock rounding', ['00:00:00:01', 16, 1000], 63), ('partial repair variant: clock rounding', ['100:59:59.0005', 40, 1000], 363599001), ('boundary control', ['3f', 16, 1000], 188), ('boundary control', ['00:00:00:25', 25, 1000], None), ('normal control', ['15m', 30, 1000], 900000), ('normal control', ['10:59:00:15', 40, 90000], 39540375), ('normal control', ['00:00:59:12', 30, 10000000], 59400)], [('regression: clock rounding', ['00:30:00:15', 16, 10000000], 1800938), ('regression variant: clock rounding', ['100:59:00.0005', 16, 3], 363540001), ('partial repair probe: clock rounding', ['100:30:59.0005', 40, 3], 361859001), ('partial repair variant: clock rounding', ['10:00:00.0005', 50, 3], 36000001), ('boundary control', ['00:00:00:25', 25, 1000], None), ('boundary control', ['10t', 25, 1000], 10), ('normal control', ['100:30:59:30', 25, 10000000], None), ('normal control', ['15t', 30, 3], 5000), ('normal control', ['01:60:05:12', 16, 10000000], None)], [('regression: clock rounding', ['00:30:00:01', 24, 1000], 1800042), ('regression variant: clock rounding', ['00:00:00:01', 16, 1000], 63), ('partial repair probe: clock rounding', ['01:30:05.0005', 30, 1000], 5405001), ('partial repair variant: clock rounding', ['10:30:05.0005', 30, 90000], 37805001), ('boundary control', ['10t', 25, 1000], 10), ('boundary control', ['3f', 16, 1000], 188), ('normal control', ['0t', 24, 3], 0), ('normal control', ['1.5t', 16, 3], 500), ('normal control', ['10:00:00.25', 16, 3], 36000250)], [('regression: clock rounding', ['01:59:59:01', 24, 3], 7199042), ('regression variant: clock rounding', ['100:30:00:15', 16, 90000], 361800938), ('partial repair probe: clock rounding', ['00:30:00.0005', 40, 3], 1800001), ('partial repair variant: clock rounding', ['00:59:00.0005', 24, 10000000], 3540001), ('boundary control', ['3f', 16, 1000], 188), ('boundary control', ['00:00:00:25', 25, 1000], None), ('normal control', ['10:30:59.5', 24, 1000], 37859500), ('normal control', ['01:30:05:25', 16, 90000], None), ('normal control', ['17h', 24, 10000000], 61200000)]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: clock rounding | 1938 | 1938 | Passed |
| regression variant: clock rounding | 39599000 | 39599001 | Failed |
| partial repair probe: clock rounding | 363540000 | 363540001 | Failed |
| partial repair variant: clock rounding | 37800000 | 37800001 | Failed |
| boundary control | 10 | 10 | Passed |
| boundary control | 188 | 188 | Passed |
| normal control | None | None | Passed |
| normal control | 39599375 | 39599375 | Passed |
| normal control | 54000000 | 54000000 | Passed |
SHA-256 / 353878981f0ef25038959975c66153450d8cc5bb5c36677e3c0173b5ea3fe5b7
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import math
import re
from fractions import Fraction
N = 1
observations = []
def solve(expr, frame_rate, tick_rate):
m=re.fullmatch(r'(\d+(?:\.\d+)?)(h|ms|m|s|f|t)',expr)
if m:
v=Fraction(m.group(1))
unit=m.group(2)
scale={'h':3600000,'m':60000,'s':1000,'ms':1}
if unit in scale:
x=v*scale[unit]
elif unit=='f':
x=v*1000/frame_rate
else:
x=v*1000/tick_rate
return math.floor(x+Fraction(1,2))
m=re.fullmatch(r'(\d{2,}):(\d{2}):(\d{2})(?:\.(\d+)|:(\d{2,}))?',expr)
if not m:
return None
h,mi,se,frac,fr=m.groups()
if int(mi)>59 or int(se)>59:
return None
x=Fraction(int(h)*3600+int(mi)*60+int(se))*1000
if frac:
x+=Fraction('0.'+frac)*1000
if fr:
if int(fr)>=frame_rate:
return None
x+=Fraction(int(fr)*1000,frame_rate)
return (x*2+1)//2
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: clock rounding', ['00:00:01:15', 16, 1000], 1938), ('regression variant: clock rounding', ['10:59:59.0005', 50, 90000], 39599001), ('partial repair probe: clock rounding', ['100:59:00.0005', 16, 3], 363540001), ('partial repair variant: clock rounding', ['10:30:00.0005', 24, 90000], 37800001), ('boundary control', ['10t', 25, 1000], 10), ('boundary control', ['3f', 16, 1000], 188), ('normal control', ['00:00:00:25', 25, 1000], None), ('normal control', ['10:59:59:15', 40, 1000], 39599375), ('normal control', ['15h', 50, 1000], 54000000)], [('regression: clock rounding', ['00:00:01.0005', 25, 1000], 1001), ('regression variant: clock rounding', ['10:59:59:29', 30, 90000], 39599967), ('partial repair probe: clock rounding', ['00:00:00:01', 16, 1000], 63), ('partial repair variant: clock rounding', ['100:59:59.0005', 40, 1000], 363599001), ('boundary control', ['3f', 16, 1000], 188), ('boundary control', ['00:00:00:25', 25, 1000], None), ('normal control', ['15m', 30, 1000], 900000), ('normal control', ['10:59:00:15', 40, 90000], 39540375), ('normal control', ['00:00:59:12', 30, 10000000], 59400)], [('regression: clock rounding', ['00:30:00:15', 16, 10000000], 1800938), ('regression variant: clock rounding', ['100:59:00.0005', 16, 3], 363540001), ('partial repair probe: clock rounding', ['100:30:59.0005', 40, 3], 361859001), ('partial repair variant: clock rounding', ['10:00:00.0005', 50, 3], 36000001), ('boundary control', ['00:00:00:25', 25, 1000], None), ('boundary control', ['10t', 25, 1000], 10), ('normal control', ['100:30:59:30', 25, 10000000], None), ('normal control', ['15t', 30, 3], 5000), ('normal control', ['01:60:05:12', 16, 10000000], None)], [('regression: clock rounding', ['00:30:00:01', 24, 1000], 1800042), ('regression variant: clock rounding', ['00:00:00:01', 16, 1000], 63), ('partial repair probe: clock rounding', ['01:30:05.0005', 30, 1000], 5405001), ('partial repair variant: clock rounding', ['10:30:05.0005', 30, 90000], 37805001), ('boundary control', ['10t', 25, 1000], 10), ('boundary control', ['3f', 16, 1000], 188), ('normal control', ['0t', 24, 3], 0), ('normal control', ['1.5t', 16, 3], 500), ('normal control', ['10:00:00.25', 16, 3], 36000250)], [('regression: clock rounding', ['01:59:59:01', 24, 3], 7199042), ('regression variant: clock rounding', ['100:30:00:15', 16, 90000], 361800938), ('partial repair probe: clock rounding', ['00:30:00.0005', 40, 3], 1800001), ('partial repair variant: clock rounding', ['00:59:00.0005', 24, 10000000], 3540001), ('boundary control', ['3f', 16, 1000], 188), ('boundary control', ['00:00:00:25', 25, 1000], None), ('normal control', ['10:30:59.5', 24, 1000], 37859500), ('normal control', ['01:30:05:25', 16, 90000], None), ('normal control', ['17h', 24, 10000000], 61200000)]]
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: clock rounding | 1938 | 1938 | Passed |
| regression variant: clock rounding | 39599001 | 39599001 | Passed |
| partial repair probe: clock rounding | 363540001 | 363540001 | Passed |
| partial repair variant: clock rounding | 37800001 | 37800001 | Passed |
| boundary control | 10 | 10 | Passed |
| boundary control | 188 | 188 | Passed |
| normal control | None | None | Passed |
| normal control | 39599375 | 39599375 | Passed |
| normal control | 54000000 | 54000000 | Passed |
SHA-256 / bf4e74a7da931bca0e343c55f4b7c46d26a5105996725e8b002075d03e4b2f5e
Verification & scope
A deterministic bounded teaching model with a stipulated toy contract; it does not claim conformance to any subtitle standard. 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:49:33.333928+00:00.
Case digest / cf6c03dd539c29a1cf597a736ae60ea3e8dafe12be08f53cf89a76c9cdcfd001