"""Historical London civil-time mapping using installed timezone data; no scheduler."""
import json,hashlib
from pathlib import Path
from datetime import datetime,timezone
from zoneinfo import ZoneInfo,TZPATH
zone=ZoneInfo('Europe/London')
def instants(text):
 wall=datetime.fromisoformat(text);out=set()
 for fold in (0,1):
  local=wall.replace(tzinfo=zone,fold=fold);utc=local.astimezone(timezone.utc)
  if utc.astimezone(zone).replace(tzinfo=None)==wall:out.add(utc.isoformat())
 return sorted(out)
cases={t:instants(t) for t in ['2024-01-15T09:00','2024-07-15T09:00','2024-10-27T01:30','2024-03-31T01:30']}
assert cases['2024-10-27T01:30']==['2024-10-27T00:30:00+00:00','2024-10-27T01:30:00+00:00']
assert cases['2024-03-31T01:30']==[]
def utc(t):return datetime.fromisoformat(instants(t)[0])
intervals={'spring09Hours':(utc('2024-03-31T09:00')-utc('2024-03-30T09:00')).total_seconds()/3600,
'autumn09Hours':(utc('2024-10-27T09:00')-utc('2024-10-26T09:00')).total_seconds()/3600}
assert intervals=={'spring09Hours':23.0,'autumn09Hours':25.0}
source={}
for base in TZPATH:
 p=Path(base)/'Europe/London'
 if p.exists():
  source={'zonefile':str(p),'sha256':hashlib.sha256(p.read_bytes()).hexdigest()}
  v=Path(base)/'tzdata.zi'
  if v.exists():source['tzdataHeader']=v.read_text().splitlines()[0]
  break
report={'zone':'Europe/London','source':source,'mappings':cases,'intervals':intervals}
if __name__=='__main__':print(json.dumps(report,indent=2))
