- commit
- efe0b9bab4cdce866b9bb1b6e09800887c36a20e
- parent
- 0e13df517856dadd45812f9db0c10a1fd241f8f3
- Author
- Tobias Bengfort <tobias.bengfort@posteo.de>
- Date
- 2025-05-30 17:20
extract validity and use it to anchor leg dates
Diffstat
| M | db_pkpass.py | 58 | ++++++++++++++++++++++++++++++++++++++++++++-------------- |
1 files changed, 44 insertions, 14 deletions
diff --git a/db_pkpass.py b/db_pkpass.py
@@ -25,6 +25,8 @@ BARCODE_FORMATS = zxingcpp.BarcodeFormats( 25 25 or zxingcpp.BarcodeFormat.QRCode 26 26 ) 27 27 -1 28 TZ = ZoneInfo('Europe/Berlin') -1 29 28 30 ICON = base64.b64decode(""" 29 31 iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAAAAXNSR0IArs4c6QAAAARnQU1BAACx 30 32 jwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAADNQTFRF @@ -60,6 +62,10 @@ def dump_pkpass(files: dict[str, bytes]) -> bytes: 60 62 return buf.getvalue() 61 63 62 64 -1 65 def strptime(s, _format): -1 66 return datetime.datetime.strptime(s, _format).astimezone(TZ) -1 67 -1 68 63 69 def extract_barcodes(pdf): 64 70 barcodes = [] 65 71 for page in pdf: @@ -73,17 +79,11 @@ def extract_barcodes(pdf): 73 79 return barcodes 74 80 75 8176 -1 def parse_leg_dt(datestr, timestr, prefix):77 -1 tz = ZoneInfo('Europe/Berlin')78 -1 now = datetime.datetime.now(tz=tz)79 -1 year = now.year80 -181 -1 f = f'%Y %d.%m. {prefix} %H:%M'82 -1 s = f'{year} {datestr} {timestr}'83 -1 dt = datetime.datetime.strptime(s, f).astimezone(tz)84 -1 if dt < now:85 -1 s = f'{year + 1} {datestr} {timestr}'86 -1 dt = datetime.datetime.strptime(s, f).astimezone(tz)-1 82 def parse_leg_dt(datestr, timestr, prefix, start): -1 83 f = f'%d.%m.%Y {prefix} %H:%M' -1 84 dt = strptime(f'{datestr}{start.year} {timestr}', f) -1 85 if dt < start: -1 86 dt = strptime(f'{datestr}{start.year + 1} {timestr}', f) 87 87 return dt 88 88 89 89 @@ -91,6 +91,7 @@ def extract_legs(pdf): 91 91 legs = [] 92 92 state = 0 93 93 last_x = 0 -1 94 validity = extract_validity(pdf) 94 95 for page in pdf: 95 96 for x, _, _, _, text, _, _ in page.get_text('blocks'): 96 97 text = text.rstrip('\n').replace(',\n', ', ') @@ -122,8 +123,12 @@ def extract_legs(pdf): 122 123 v1, v2 = (v.strip() for v in text.rstrip('\n').split('\n')) 123 124 date1 = legs[-1]['start'].pop('date') 124 125 date2 = legs[-1]['destination'].pop('date')125 -1 legs[-1]['start']['datetime'] = parse_leg_dt(date1, v1, 'ab')126 -1 legs[-1]['destination']['datetime'] = parse_leg_dt(date2, v2, 'an')-1 126 legs[-1]['start']['datetime'] = parse_leg_dt( -1 127 date1, v1, 'ab', validity[0] -1 128 ) -1 129 legs[-1]['destination']['datetime'] = parse_leg_dt( -1 130 date2, v2, 'an', validity[0] -1 131 ) 127 132 state = 4 128 133 elif state == 4: 129 134 v1, v2 = (v.strip() for v in text.rstrip('\n').split('\n')) @@ -158,6 +163,23 @@ def extract_order_id(pdf): 158 163 return text[len(key):] 159 164 160 165 -1 166 def extract_validity(pdf): -1 167 key1 = 'Gültigkeit: ' -1 168 key2 = 'Fahrtantritt am ' -1 169 for page in pdf: -1 170 for text in page.get_text().split('\n'): -1 171 if text.startswith(key1): -1 172 s_start, s_end = text[len(key1):].split(' bis ') -1 173 start = strptime(s_start, '%d.%m.%Y %H:%M Uhr') -1 174 end = strptime(s_end, '%d.%m.%Y %H:%M Uhr') -1 175 return start, end -1 176 elif text.startswith(key2): -1 177 s_start = text[len(key2):] -1 178 start = strptime(s_start, '%d.%m.%Y') -1 179 end = start + datetime.timedelta(days=1) -1 180 return start, end -1 181 -1 182 161 183 def format_stop(stop, train=None): 162 184 t = stop['datetime'].strftime('%H:%M') 163 185 s = f'{t} {stop["station"]}' @@ -178,8 +200,9 @@ def format_legs(legs): 178 200 179 201 def extract_content(pdf): 180 202 order_id = extract_order_id(pdf) -1 203 validity = extract_validity(pdf) 181 204182 -1 legs = extract_legs(pdf)-1 205 legs = extract_legs(pdf, validity[0]) 183 206 start = legs[0]['start']['station'] 184 207 destination = legs[-1]['destination']['station'] 185 208 date = legs[0]['start']['datetime'] @@ -191,6 +214,13 @@ def extract_content(pdf): 191 214 'teamIdentifier': 'XXXXXXXXXX', 192 215 'serialNumber': order_id, 193 216 'description': f'{start} → {destination} ({date.date().isoformat()})', -1 217 'expirationDate': validity[1].isoformat(), -1 218 'relevantDates': [ -1 219 { -1 220 'startDate': validity[0].isoformat(), -1 221 'endDate': validity[1].isoformat(), -1 222 }, -1 223 ], 194 224 'barcodes': [ 195 225 { 196 226 'format': _format,