derhuerst / db-rest

A clean REST API wrapping around the Deutsche Bahn API.
https://v6.db.transport.rest/
ISC License
86 stars 10 forks source link

Timezone issue for journey advices in UK #54

Open Treinfan opened 2 months ago

Treinfan commented 2 months ago

Hi,

I have been using your API for a while now with success, but I have noticed some strange behaviour when planning journeys inside the UK. Despite the timezone parameters being correct and the returned data being correct, the advices are shown for one hour later than requested. For example, this request, departure time 07:00+01:00 doesn't show the trains departing at 06:56+01:00 and 07:21+01:00, but gives the trains departing at 08:21+01:00, 09:21+01:00 and 10:05+01:00. I can see that the timezone in the parameter is processed, because 08:00+02:00 gives exactly the same result as 07:00+01:00.

derhuerst commented 1 month ago

TLDR: I think this is a bug in HAFAS and that db-rest cannot solve this in a clean way.

background

AFAIK – I might be wrong, or things might have changed by now! – all HAFAS requests (not responses) are timezone-unaware.

  1. A HAFAS instance has configured a single "native" timezone in which it interprets the timezone-(offset)-less outDate/outTime request fields.
  2. It then does the routing, and for all results, if it knows the timezone offset of a stop, will add it as {a,d}TZOffset and translates {a,d}Time{S,R} accordingly.
  3. hafas-client has no other choice than working with what HAFAS has responded with (introduced here).

db-rest could tell hafas-client to forcefully interpret the response fields in a specific (different) timezone, but it would have to know all stop IDs which to apply this to, otherwise it would accidentally

This is why I consider maintaining logic which decides which non-Europe/Berlin stops to apply this transformation to as rather unsustainable.

analysis

I ran db-rest@6 locally with DEBUG=hafas-client and then requested http://localhost:3000/journeys?from=7000616&to=7001369&via=&stopovers=true&language=nl&departure=2024-10-02T07:00:00%2b01:00. (Just for clarity: I'm using a future date here to make sure my requests can be reproduced for a while, but the findings should be applicable nonetheless.)

HAFAS request sent by `db-rest`/`hafas-client` ```json { "lang": "nl", "svcReqL": [ { "cfg": { "polyEnc": "GPA", "rtMode": "REALTIME" }, "meth": "TripSearch", "req": { "getPasslist": true, "maxChg": -1, "minChgTime": 0, "depLocL": [ { "type": "S", "lid": "A=1@L=7000616@" } ], "viaLocL": [], "arrLocL": [ { "type": "S", "lid": "A=1@L=7001369@" } ], "jnyFltrL": [ { "type": "PROD", "mode": "INC", "value": "1023" }, { "type": "META", "mode": "INC", "meta": "notBarrierfree" } ], "gisFltrL": [], "getTariff": false, "ushrp": true, "getPT": true, "getIV": false, "getPolyline": false, "outDate": "20241002", "outTime": "080000", "numF": 3, "outFrwd": true, "trfReq": { "jnyCl": 2, "tvlrProf": [ { "type": "E", "redtnCard": null } ], "cType": "PK" } } } ], "client": { "type": "AND", "id": "DB", "v": 21120000, "name": "DB Navigator" }, "ext": "DB.R21.12.a", "ver": "1.34", "auth": { "type": "AID", "aid": "n91dB8Z77MLdoR0K" } } ```
HAFAS response ```json { "ver": "1.34", "ext": "DB.R21.12.a", "lang": "nld", "id": "vamkajxciqm3ymck", "err": "OK", "cInfo": { "code": "OK" }, "graph": { "id": "standard", "index": 0 }, "subGraph": { "id": "global", "index": 0 }, "view": { "id": "standard", "index": 0, "type": "WGS84" }, "svcResL": [ { "meth": "TripSearch", "err": "OK", "res": { "common": { "locL": [ { "lid": "A=1@O=Crewe@X=-2432724@Y=53088943@U=80@L=7000616@i=U×007012430@", "type": "S", "name": "Crewe", "icoX": 0, "extId": "7000616", "state": "F", "crd": { "x": -2432724, "y": 53088943, "floor": 0 }, "pCls": 12, "gidL": [ "U×007012430" ] }, { "lid": "A=1@O=Chester@X=-2879344@Y=53196652@U=80@L=7000468@i=U×007024120@", "type": "S", "name": "Chester", "icoX": 0, "extId": "7000468", "state": "F", "crd": { "x": -2879344, "y": 53196652, "floor": 0 }, "pCls": 44, "gidL": [ "U×007024120" ] }, { "lid": "A=1@O=Llandudno Junction@X=-3809044@Y=53284054@U=80@L=7001369@i=U×007024850@", "type": "S", "name": "Llandudno Junction", "icoX": 0, "extId": "7001369", "state": "F", "crd": { "x": -3809044, "y": 53284054, "floor": 0 }, "pCls": 12, "gidL": [ "U×007024850" ] }, { "lid": "A=1@O=Shotton@X=-3037230@Y=53213794@U=80@L=7002095@i=U×007025460@", "type": "S", "name": "Shotton", "icoX": 0, "extId": "7002095", "state": "F", "crd": { "x": -3037230, "y": 53213794, "floor": 0 }, "pCls": 12, "gidL": [ "U×007025460" ] }, { "lid": "A=1@O=Flint@X=-3132318@Y=53249742@U=80@L=7000865@i=U×007025130@", "type": "S", "name": "Flint", "icoX": 0, "extId": "7000865", "state": "F", "crd": { "x": -3132318, "y": 53249742, "floor": 0 }, "pCls": 12, "gidL": [ "U×007025130" ] }, { "lid": "A=1@O=Prestatyn@X=-3407352@Y=53336228@U=80@L=7001793@i=U×007025210@", "type": "S", "name": "Prestatyn", "icoX": 0, "extId": "7001793", "state": "F", "crd": { "x": -3407352, "y": 53336228, "floor": 0 }, "pCls": 12, "gidL": [ "U×007025210" ] }, { "lid": "A=1@O=Rhyl@X=-3488956@Y=53318150@U=80@L=7001872@i=U×007024610@", "type": "S", "name": "Rhyl", "icoX": 0, "extId": "7001872", "state": "F", "crd": { "x": -3488956, "y": 53318150, "floor": 0 }, "pCls": 12, "gidL": [ "U×007024610" ] }, { "lid": "A=1@O=Abergele *26 Pensarn@X=-3582705@Y=53294679@U=80@L=7000017@i=U×007024480@", "type": "S", "name": "Abergele & Pensarn", "icoX": 0, "extId": "7000017", "state": "F", "crd": { "x": -3582705, "y": 53294679, "floor": 0 }, "pCls": 12, "gidL": [ "U×007024480" ] }, { "lid": "A=1@O=Colwyn Bay@X=-3725966@Y=53296855@U=80@L=7000618@i=U×007024510@", "type": "S", "name": "Colwyn Bay", "icoX": 0, "extId": "7000618", "state": "F", "crd": { "x": -3725966, "y": 53296855, "floor": 0 }, "pCls": 12, "gidL": [ "U×007024510" ] } ], "prodL": [ { "name": "", "number": "39493", "icoX": 0, "cls": 4, "oprX": 0, "prodCtx": { "name": " ", "num": "39493", "matchId": "L39493", "catOutS": "X70", "catOutL": "Schnellzug", "catIn": "X70", "catCode": "2", "admin": "70AW-L" } }, { "name": "", "number": "39368", "icoX": 0, "cls": 4, "oprX": 0, "prodCtx": { "name": " ", "num": "39368", "matchId": "L39368", "catOutS": "X70", "catOutL": "Schnellzug", "catIn": "X70", "catCode": "2", "admin": "70AW-L" } }, { "name": "Overstap", "icoX": 4, "prodCtx": { "name": "Overstap" } }, { "name": "", "number": "39497", "icoX": 0, "cls": 4, "oprX": 0, "prodCtx": { "name": " ", "num": "39497", "matchId": "L39497", "catOutS": "X70", "catOutL": "Schnellzug", "catIn": "X70", "catCode": "2", "admin": "70AW-L" } }, { "name": "", "number": "39379", "icoX": 0, "cls": 4, "oprX": 0, "prodCtx": { "name": " ", "num": "39379", "matchId": "L39379", "catOutS": "X70", "catOutL": "Schnellzug", "catIn": "X70", "catCode": "2", "admin": "70AW-L" } }, { "name": "", "number": "39455", "icoX": 0, "cls": 4, "oprX": 0, "prodCtx": { "name": " ", "num": "39455", "matchId": "L39455", "catOutS": "X70", "catOutL": "Schnellzug", "catIn": "X70", "catCode": "2", "admin": "70AW-L" } } ], "opL": [ { "name": "Wales & Borders", "icoX": 1 } ], "remL": [ { "type": "A", "code": "K2", "prio": 300, "icoX": 2, "txtN": "alleen 2e Klas" }, { "type": "A", "code": "RM", "prio": 320, "icoX": 3, "txtN": "Reserveren mogelijk" }, { "type": "A", "code": "RE", "prio": 320, "icoX": 3, "txtN": "Reserveren aanbevolen" } ], "icoL": [ { "res": "prod_gen" }, { "res": "U70", "txt": "Wales & Borders" }, { "res": "attr_2nd" }, { "res": "attr_info" }, { "res": "prod_walk" }, { "res": "cl_all" } ], "dirL": [ { "txt": "Chester" }, { "txt": "Llandudno" }, { "txt": "Holyhead" } ], "lDrawStyleL": [ { "sIcoX": 0, "type": "SOLID" }, { "type": "SOLID" }, { "sIcoX": 4, "type": "DOT" }, { "type": "DOT" } ] }, "outConL": [ { "cid": "C-0", "date": "20241002", "dur": "013000", "durS": "013000", "durR": "013000", "chg": 1, "sDays": { "sDaysR": "rijdt Ma - Vr ", "sDaysB": "000000000000000000000000000000000000000000000000000000000000000000003E7CF9F3E7CF9F3E7CF9F3E7C0" }, "dep": { "locX": 0, "idx": 0, "dProdX": 0, "dPltfS": { "type": "PL", "txt": "10" }, "dTimeS": "082100", "dProgType": "PROGNOSED", "dTZOffset": 60, "type": "N" }, "arr": { "locX": 2, "idx": 17, "aProdX": 1, "aPltfS": { "type": "PL", "txt": "4" }, "aTimeS": "095100", "aTZOffset": 60, "type": "N" }, "secL": [ { "type": "JNY", "dep": { "locX": 0, "idx": 0, "dProdX": 0, "dPltfS": { "type": "PL", "txt": "10" }, "dTimeS": "082100", "dProgType": "PROGNOSED", "dTZOffset": 60, "type": "N" }, "arr": { "locX": 1, "idx": 1, "aProdX": 0, "aPltfS": { "type": "PL", "txt": "1" }, "aTimeS": "084400", "aProgType": "PROGNOSED", "aTZOffset": 60, "type": "N" }, "jny": { "jid": "2|#VN#1#ST#1727117920#PI#0#ZI#175563#TA#0#DA#21024#1S#7000616#1T#821#LS#7000468#LT#844#PU#80#RT#1#CA#X70#ZE#39493#ZB# #PC#2#FR#7000616#FT#821#TO#7000468#TT#844#", "date": "20241002", "prodX": 0, "dirTxt": "Chester", "status": "P", "isRchbl": true, "stopL": [ { "locX": 0, "idx": 0, "dProdX": 0, "dPltfS": { "type": "PL", "txt": "10" }, "dTimeS": "082100", "dProgType": "PROGNOSED", "dDirTxt": "Chester", "dTZOffset": 60, "type": "N" }, { "locX": 1, "idx": 1, "aProdX": 0, "aPltfS": { "type": "PL", "txt": "1" }, "aTimeS": "084400", "aProgType": "PROGNOSED", "aTZOffset": 60, "type": "N" } ], "ctxRecon": "T$A=1@O=Crewe@L=7000616@a=128@$A=1@O=Chester@L=7000468@a=128@$202410020821$202410020844$ $$1$$$$$$", "msgL": [ { "type": "REM", "remX": 0, "sty": "I", "fLocX": 0, "tLocX": 1, "fIdx": 0, "tIdx": 1, "tagL": [ "RES_JNY_DTL_L" ], "sort": 844627968 }, { "type": "REM", "remX": 1, "sty": "I", "fLocX": 0, "tLocX": 1, "fIdx": 0, "tIdx": 1, "tagL": [ "RES_JNY_DTL" ], "sort": 847249408 } ], "subscr": "F", "chgDurR": 11, "prodL": [ { "prodX": 0, "fLocX": 0, "tLocX": 1, "fIdx": 0, "tIdx": 1 } ], "dirL": [ { "dirX": 0, "fLocX": 0, "tLocX": 1, "fIdx": 0, "tIdx": 1 } ], "sumLDrawStyleX": 0, "resLDrawStyleX": 1, "trainStartDate": "20241002", "durS": "002300" }, "minChg": "000500", "resState": "N", "resRecommendation": "N" }, { "type": "WALK", "dep": { "locX": 1, "dPltfS": { "type": "PL", "txt": "1" }, "dTimeS": "084400", "dTZOffset": 60 }, "arr": { "locX": 1, "aPltfS": { "type": "PL", "txt": "3" }, "aTimeS": "084400", "aTZOffset": 60 }, "gis": { "gisPrvr": "H", "sumLDrawStyleX": 2, "resLDrawStyleX": 3, "prodX": 2 }, "resRecommendation": "U" }, { "type": "JNY", "dep": { "locX": 1, "idx": 10, "dProdX": 1, "dPltfS": { "type": "PL", "txt": "3" }, "dTimeS": "085500", "dTZOffset": 60, "type": "N" }, "arr": { "locX": 2, "idx": 17, "aProdX": 1, "aPltfS": { "type": "PL", "txt": "4" }, "aTimeS": "095100", "aTZOffset": 60, "type": "N" }, "jny": { "jid": "2|#VN#1#ST#1727117920#PI#0#ZI#175353#TA#0#DA#21024#1S#7002677#1T#725#LS#7001321#LT#1001#PU#80#RT#1#CA#X70#ZE#39368#ZB# #PC#2#FR#7002677#FT#725#TO#7001321#TT#1001#", "date": "20241002", "prodX": 1, "dirTxt": "Llandudno", "status": "P", "isRchbl": true, "stopL": [ { "locX": 1, "idx": 10, "dProdX": 1, "dPltfS": { "type": "PL", "txt": "3" }, "dTimeS": "085500", "dDirTxt": "Llandudno", "dTZOffset": 60, "type": "N" }, { "locX": 3, "idx": 11, "aProdX": 1, "aTimeS": "090400", "aTZOffset": 60, "dProdX": 1, "dTimeS": "090400", "dTZOffset": 60, "type": "N" }, { "locX": 4, "idx": 12, "aProdX": 1, "aTimeS": "091000", "aTZOffset": 60, "dProdX": 1, "dTimeS": "091000", "dTZOffset": 60, "type": "N" }, { "locX": 5, "idx": 13, "aProdX": 1, "aTimeS": "092300", "aTZOffset": 60, "dProdX": 1, "dTimeS": "092300", "dTZOffset": 60, "type": "N" }, { "locX": 6, "idx": 14, "aProdX": 1, "aPltfS": { "type": "PL", "txt": "2" }, "aTimeS": "093000", "aTZOffset": 60, "dProdX": 1, "dPltfS": { "type": "PL", "txt": "2" }, "dTimeS": "093000", "dTZOffset": 60, "type": "N" }, { "locX": 7, "idx": 15, "aProdX": 1, "aTimeS": "093600", "aTZOffset": 60, "dProdX": 1, "dTimeS": "093600", "dTZOffset": 60, "type": "N" }, { "locX": 8, "idx": 16, "aProdX": 1, "aTimeS": "094400", "aTZOffset": 60, "dProdX": 1, "dTimeS": "094400", "dTZOffset": 60, "type": "N" }, { "locX": 2, "idx": 17, "aProdX": 1, "aPltfS": { "type": "PL", "txt": "4" }, "aTimeS": "095100", "aTZOffset": 60, "type": "N" } ], "ctxRecon": "T$A=1@O=Chester@L=7000468@a=128@$A=1@O=Llandudno Junction@L=7001369@a=128@$202410020855$202410020951$ $$1$$$$$$", "msgL": [ { "type": "REM", "remX": 0, "sty": "I", "fLocX": 1, "tLocX": 2, "fIdx": 10, "tIdx": 17, "tagL": [ "RES_JNY_DTL_L" ], "sort": 844627968 }, { "type": "REM", "remX": 2, "sty": "I", "fLocX": 1, "tLocX": 2, "fIdx": 10, "tIdx": 17, "tagL": [ "RES_JNY_DTL" ], "sort": 847249408 } ], "subscr": "F", "prodL": [ { "prodX": 1, "fLocX": 1, "tLocX": 2, "fIdx": 10, "tIdx": 17 } ], "dirL": [ { "dirX": 1, "fLocX": 1, "tLocX": 2, "fIdx": 10, "tIdx": 17 } ], "sumLDrawStyleX": 0, "resLDrawStyleX": 1, "trainStartDate": "20241002", "durS": "005600" }, "resState": "N", "resRecommendation": "N" } ], "ctxRecon": "T$A=1@O=Crewe@L=7000616@a=128@$A=1@O=Chester@L=7000468@a=128@$202410020821$202410020844$ $$1$$$$$$§T$A=1@O=Chester@L=7000468@a=128@$A=1@O=Llandudno Junction@L=7001369@a=128@$202410020855$202410020951$ $$1$$$$$$", "trfRes": { "statusCode": "NA", "fareSetL": [ { "fareL": [ { "desc": "Fares not available", "isFromPrice": false, "isPartPrice": false, "isBookable": true, "isUpsell": false, "bookStatus": "VIA_MCP", "price": { "amount": -1 }, "retPriceIsCompletePrice": false, "retPrice": -1 } ] } ] }, "conSubscr": "N", "resState": "N", "resRecommendation": "N", "recState": "U", "sotRating": 0, "isSotCon": false, "showARSLink": false, "sotCtxt": { "cnLocX": 0, "calcDate": "20240925", "jid": "2|#VN#1#ST#1727117920#PI#0#ZI#175563#TA#0#DA#90924#1S#7000616#1T#821#LS#7000468#LT#844#PU#80#RT#1#CA#X70#ZE#39493#ZB# #PC#2#FR#7000616#FT#821#TO#7000468#TT#844#", "locMode": "FROM_START", "pLocX": 0, "reqMode": "UNKNOWN", "sectX": 0, "calcTime": "224426" }, "cksum": "9d83d711_3", "cksumDti": "6ab0217f_3", "intvlSubscr": "F", "originType": "INITIAL" }, { "cid": "C-1", "date": "20241002", "dur": "012800", "durS": "012800", "durR": "012800", "chg": 1, "sDays": { "sDaysR": "rijdt Ma - Vr ", "sDaysB": "000000000000000000000000000000000000000000000000000000000000000000003E7CF9F3E7CF9F3E7CF9F3E7C0" }, "dep": { "locX": 0, "idx": 0, "dProdX": 3, "dPltfS": { "type": "PL", "txt": "9" }, "dTimeS": "092100", "dProgType": "PROGNOSED", "dTZOffset": 60, "type": "N" }, "arr": { "locX": 2, "idx": 16, "aProdX": 4, "aPltfS": { "type": "PL", "txt": "3" }, "aTimeS": "104900", "aTZOffset": 60, "type": "N" }, "secL": [ { "type": "JNY", "dep": { "locX": 0, "idx": 0, "dProdX": 3, "dPltfS": { "type": "PL", "txt": "9" }, "dTimeS": "092100", "dProgType": "PROGNOSED", "dTZOffset": 60, "type": "N" }, "arr": { "locX": 1, "idx": 1, "aProdX": 3, "aPltfS": { "type": "PL", "txt": "1" }, "aTimeS": "094400", "aProgType": "PROGNOSED", "aTZOffset": 60, "type": "N" }, "jny": { "jid": "2|#VN#1#ST#1727117920#PI#0#ZI#175563#TA#1#DA#21024#1S#7000616#1T#921#LS#7000468#LT#944#PU#80#RT#1#CA#X70#ZE#39497#ZB# #PC#2#FR#7000616#FT#921#TO#7000468#TT#944#", "date": "20241002", "prodX": 3, "dirTxt": "Chester", "status": "P", "isRchbl": true, "stopL": [ { "locX": 0, "idx": 0, "dProdX": 3, "dPltfS": { "type": "PL", "txt": "9" }, "dTimeS": "092100", "dProgType": "PROGNOSED", "dDirTxt": "Chester", "dTZOffset": 60, "type": "N" }, { "locX": 1, "idx": 1, "aProdX": 3, "aPltfS": { "type": "PL", "txt": "1" }, "aTimeS": "094400", "aProgType": "PROGNOSED", "aTZOffset": 60, "type": "N" } ], "ctxRecon": "T$A=1@O=Crewe@L=7000616@a=128@$A=1@O=Chester@L=7000468@a=128@$202410020921$202410020944$ $$1$$$$$$", "msgL": [ { "type": "REM", "remX": 0, "sty": "I", "fLocX": 0, "tLocX": 1, "fIdx": 0, "tIdx": 1, "tagL": [ "RES_JNY_DTL_L" ], "sort": 844627968 }, { "type": "REM", "remX": 1, "sty": "I", "fLocX": 0, "tLocX": 1, "fIdx": 0, "tIdx": 1, "tagL": [ "RES_JNY_DTL" ], "sort": 847249408 } ], "subscr": "F", "chgDurR": 15, "prodL": [ { "prodX": 3, "fLocX": 0, "tLocX": 1, "fIdx": 0, "tIdx": 1 } ], "dirL": [ { "dirX": 0, "fLocX": 0, "tLocX": 1, "fIdx": 0, "tIdx": 1 } ], "sumLDrawStyleX": 0, "resLDrawStyleX": 1, "trainStartDate": "20241002", "durS": "002300" }, "minChg": "000500", "resState": "N", "resRecommendation": "N" }, { "type": "WALK", "dep": { "locX": 1, "dPltfS": { "type": "PL", "txt": "1" }, "dTimeS": "094400", "dTZOffset": 60 }, "arr": { "locX": 1, "aPltfS": { "type": "PL", "txt": "3" }, "aTimeS": "094400", "aTZOffset": 60 }, "gis": { "gisPrvr": "H", "sumLDrawStyleX": 2, "resLDrawStyleX": 3, "prodX": 2 }, "resRecommendation": "U" }, { "type": "JNY", "dep": { "locX": 1, "idx": 10, "dProdX": 4, "dPltfS": { "type": "PL", "txt": "3" }, "dTimeS": "095900", "dTZOffset": 60, "type": "N" }, "arr": { "locX": 2, "idx": 16, "aProdX": 4, "aPltfS": { "type": "PL", "txt": "3" }, "aTimeS": "104900", "aTZOffset": 60, "type": "N" }, "jny": { "jid": "2|#VN#1#ST#1727117920#PI#0#ZI#175367#TA#0#DA#21024#1S#7002677#1T#825#LS#7001052#LT#1142#PU#80#RT#1#CA#X70#ZE#39379#ZB# #PC#2#FR#7002677#FT#825#TO#7001052#TT#1142#", "date": "20241002", "prodX": 4, "dirTxt": "Holyhead", "status": "P", "isRchbl": true, "stopL": [ { "locX": 1, "idx": 10, "dProdX": 4, "dPltfS": { "type": "PL", "txt": "3" }, "dTimeS": "095900", "dDirTxt": "Holyhead", "dTZOffset": 60, "type": "N" }, { "locX": 3, "idx": 11, "aProdX": 4, "aTimeS": "100700", "aTZOffset": 60, "dProdX": 4, "dTimeS": "100700", "dTZOffset": 60, "type": "N" }, { "locX": 4, "idx": 12, "aProdX": 4, "aTimeS": "101300", "aTZOffset": 60, "dProdX": 4, "dTimeS": "101300", "dTZOffset": 60, "type": "N" }, { "locX": 5, "idx": 13, "aProdX": 4, "aTimeS": "102500", "aTZOffset": 60, "dProdX": 4, "dTimeS": "102600", "dTZOffset": 60, "type": "N" }, { "locX": 6, "idx": 14, "aProdX": 4, "aPltfS": { "type": "PL", "txt": "2" }, "aTimeS": "103200", "aTZOffset": 60, "dProdX": 4, "dPltfS": { "type": "PL", "txt": "2" }, "dTimeS": "103200", "dTZOffset": 60, "type": "N" }, { "locX": 8, "idx": 15, "aProdX": 4, "aTimeS": "104200", "aTZOffset": 60, "dProdX": 4, "dTimeS": "104200", "dTZOffset": 60, "type": "N" }, { "locX": 2, "idx": 16, "aProdX": 4, "aPltfS": { "type": "PL", "txt": "3" }, "aTimeS": "104900", "aTZOffset": 60, "type": "N" } ], "ctxRecon": "T$A=1@O=Chester@L=7000468@a=128@$A=1@O=Llandudno Junction@L=7001369@a=128@$202410020959$202410021049$ $$1$$$$$$", "msgL": [ { "type": "REM", "remX": 0, "sty": "I", "fLocX": 1, "tLocX": 2, "fIdx": 10, "tIdx": 16, "tagL": [ "RES_JNY_DTL_L" ], "sort": 844627968 }, { "type": "REM", "remX": 1, "sty": "I", "fLocX": 1, "tLocX": 2, "fIdx": 10, "tIdx": 16, "tagL": [ "RES_JNY_DTL" ], "sort": 847249408 } ], "subscr": "F", "prodL": [ { "prodX": 4, "fLocX": 1, "tLocX": 2, "fIdx": 10, "tIdx": 16 } ], "dirL": [ { "dirX": 2, "fLocX": 1, "tLocX": 2, "fIdx": 10, "tIdx": 16 } ], "sumLDrawStyleX": 0, "resLDrawStyleX": 1, "trainStartDate": "20241002", "durS": "005000" }, "resState": "N", "resRecommendation": "N" } ], "ctxRecon": "T$A=1@O=Crewe@L=7000616@a=128@$A=1@O=Chester@L=7000468@a=128@$202410020921$202410020944$ $$1$$$$$$§T$A=1@O=Chester@L=7000468@a=128@$A=1@O=Llandudno Junction@L=7001369@a=128@$202410020959$202410021049$ $$1$$$$$$", "trfRes": { "statusCode": "NA", "fareSetL": [ { "fareL": [ { "desc": "Fares not available", "isFromPrice": false, "isPartPrice": false, "isBookable": true, "isUpsell": false, "bookStatus": "VIA_MCP", "price": { "amount": -1 }, "retPriceIsCompletePrice": false, "retPrice": -1 } ] } ] }, "conSubscr": "N", "resState": "N", "resRecommendation": "N", "recState": "U", "sotRating": 0, "isSotCon": false, "showARSLink": false, "sotCtxt": { "cnLocX": 0, "calcDate": "20240925", "jid": "2|#VN#1#ST#1727117920#PI#0#ZI#175563#TA#1#DA#90924#1S#7000616#1T#921#LS#7000468#LT#944#PU#80#RT#1#CA#X70#ZE#39497#ZB# #PC#2#FR#7000616#FT#921#TO#7000468#TT#944#", "locMode": "FROM_START", "pLocX": 0, "reqMode": "UNKNOWN", "sectX": 0, "calcTime": "224426" }, "cksum": "73f6a50c_3", "cksumDti": "6befa570_3", "intvlSubscr": "F", "originType": "INITIAL" }, { "cid": "C-2", "date": "20241002", "dur": "012000", "durS": "012000", "durR": "012000", "chg": 0, "sDays": { "sDaysR": "rijdt Ma - Vr ", "sDaysB": "000000000000000000000000000000000000000000000000000000000000000000003E7CF9F3E7CF9F3E7CF9F3E7C0" }, "dep": { "locX": 0, "idx": 0, "dProdX": 5, "dPltfS": { "type": "PL", "txt": "9" }, "dTimeS": "100500", "dProgType": "PROGNOSED", "dTZOffset": 60, "type": "N" }, "arr": { "locX": 2, "idx": 8, "aProdX": 5, "aPltfS": { "type": "PL", "txt": "1" }, "aTimeS": "112500", "aTZOffset": 60, "type": "N" }, "secL": [ { "type": "JNY", "dep": { "locX": 0, "idx": 0, "dProdX": 5, "dPltfS": { "type": "PL", "txt": "9" }, "dTimeS": "100500", "dProgType": "PROGNOSED", "dTZOffset": 60, "type": "N" }, "arr": { "locX": 2, "idx": 8, "aProdX": 5, "aPltfS": { "type": "PL", "txt": "1" }, "aTimeS": "112500", "aTZOffset": 60, "type": "N" }, "jny": { "jid": "2|#VN#1#ST#1727117920#PI#0#ZI#175518#TA#0#DA#21024#1S#7000616#1T#1005#LS#7001321#LT#1136#PU#80#RT#1#CA#X70#ZE#39455#ZB# #PC#2#FR#7000616#FT#1005#TO#7001321#TT#1136#", "date": "20241002", "prodX": 5, "dirTxt": "Llandudno", "status": "P", "isRchbl": true, "stopL": [ { "locX": 0, "idx": 0, "dProdX": 5, "dPltfS": { "type": "PL", "txt": "9" }, "dTimeS": "100500", "dProgType": "PROGNOSED", "dDirTxt": "Llandudno", "dTZOffset": 60, "type": "N" }, { "locX": 1, "idx": 1, "aProdX": 5, "aPltfS": { "type": "PL", "txt": "3" }, "aTimeS": "102800", "aTZOffset": 60, "dProdX": 5, "dPltfS": { "type": "PL", "txt": "3" }, "dTimeS": "102800", "dTZOffset": 60, "type": "N" }, { "locX": 3, "idx": 2, "aProdX": 5, "aTimeS": "103700", "aTZOffset": 60, "dProdX": 5, "dTimeS": "103700", "dTZOffset": 60, "type": "N" }, { "locX": 4, "idx": 3, "aProdX": 5, "aTimeS": "104400", "aTZOffset": 60, "dProdX": 5, "dTimeS": "104400", "dTZOffset": 60, "type": "N" }, { "locX": 5, "idx": 4, "aProdX": 5, "aTimeS": "105700", "aTZOffset": 60, "dProdX": 5, "dTimeS": "105700", "dTZOffset": 60, "type": "N" }, { "locX": 6, "idx": 5, "aProdX": 5, "aPltfS": { "type": "PL", "txt": "2" }, "aTimeS": "110300", "aTZOffset": 60, "dProdX": 5, "dPltfS": { "type": "PL", "txt": "2" }, "dTimeS": "110300", "dTZOffset": 60, "type": "N" }, { "locX": 7, "idx": 6, "aProdX": 5, "aTimeS": "110900", "aTZOffset": 60, "dProdX": 5, "dTimeS": "110900", "dTZOffset": 60, "type": "N" }, { "locX": 8, "idx": 7, "aProdX": 5, "aTimeS": "111800", "aTZOffset": 60, "dProdX": 5, "dTimeS": "111800", "dTZOffset": 60, "type": "N" }, { "locX": 2, "idx": 8, "aProdX": 5, "aPltfS": { "type": "PL", "txt": "1" }, "aTimeS": "112500", "aTZOffset": 60, "type": "N" } ], "ctxRecon": "T$A=1@O=Crewe@L=7000616@a=128@$A=1@O=Llandudno Junction@L=7001369@a=128@$202410021005$202410021125$ $$1$$$$$$", "msgL": [ { "type": "REM", "remX": 0, "sty": "I", "fLocX": 0, "tLocX": 2, "fIdx": 0, "tIdx": 8, "tagL": [ "RES_JNY_DTL_L" ], "sort": 844627968 } ], "subscr": "F", "prodL": [ { "prodX": 5, "fLocX": 0, "tLocX": 2, "fIdx": 0, "tIdx": 8 } ], "dirL": [ { "dirX": 1, "fLocX": 0, "tLocX": 2, "fIdx": 0, "tIdx": 8 } ], "sumLDrawStyleX": 0, "resLDrawStyleX": 1, "trainStartDate": "20241002", "durS": "012000" }, "resState": "N", "resRecommendation": "N" } ], "ctxRecon": "T$A=1@O=Crewe@L=7000616@a=128@$A=1@O=Llandudno Junction@L=7001369@a=128@$202410021005$202410021125$ $$1$$$$$$", "trfRes": { "statusCode": "NA", "fareSetL": [ { "fareL": [ { "desc": "Fares not available", "isFromPrice": false, "isPartPrice": false, "isBookable": true, "isUpsell": false, "bookStatus": "VIA_MCP", "price": { "amount": -1 }, "retPriceIsCompletePrice": false, "retPrice": -1 } ] } ] }, "conSubscr": "N", "resState": "N", "resRecommendation": "N", "recState": "U", "sotRating": 0, "isSotCon": false, "showARSLink": false, "sotCtxt": { "cnLocX": 0, "calcDate": "20240925", "jid": "2|#VN#1#ST#1727117920#PI#0#ZI#175518#TA#0#DA#100924#1S#7000616#1T#1005#LS#7001321#LT#1136#PU#80#RT#1#CA#X70#ZE#39455#ZB# #PC#2#FR#7000616#FT#1005#TO#7001321#TT#1136#", "locMode": "FROM_START", "pLocX": 0, "reqMode": "UNKNOWN", "sectX": 0, "calcTime": "224427" }, "cksum": "d6c2c2f1_3", "cksumDti": "fd4c1eb5_3", "intvlSubscr": "F", "originType": "INITIAL" } ], "fpB": "20231210", "fpE": "20241214", "bfATS": -1, "bfIOSTS": -1, "planrtTS": "1727296983", "outConGrpSettings": { "conGrpL": [ { "name": "Alle verbindingen", "icoX": 5, "grpid": "cl_all", "conScoringL": [ { "type": "DT", "conScoreL": [ { "score": 7340208785101684734, "scoreS": "07340208785101684734", "conRefL": [ 0 ] }, { "score": 7339944902312067070, "scoreS": "07339944902312067070", "conRefL": [ 1 ] }, { "score": 7339751388269772799, "scoreS": "07339751388269772799", "conRefL": [ 2 ] } ], "name": "vertrektijd" }, { "type": "AT", "conScoreL": [ { "score": 7339812960915685374, "scoreS": "07339812960915685374", "conRefL": [ 0 ] }, { "score": 7339557874219089918, "scoreS": "07339557874219089918", "conRefL": [ 1 ] }, { "score": 7339399544548884479, "scoreS": "07339399544548884479", "conRefL": [ 2 ] } ], "name": "aankomsttijd" }, { "type": "TI", "conScoreL": [ { "score": 9222972689643732990, "scoreS": "09222972689643732990", "conRefL": [ 0 ] }, { "score": 9222981485705297918, "scoreS": "09222981485705297918", "conRefL": [ 1 ] }, { "score": 9223016670054318079, "scoreS": "09223016670054318079", "conRefL": [ 2 ] } ], "name": "duur" } ], "initScoringType": "DT", "requests": [ { "id": "RQ_CLIENT", "autosend": true } ], "scrollable": true, "bitmask": 1 } ], "selectL": [ { "icoX": 5, "name": "Alle verbindingen", "bitIdx": 0 } ], "variant": "RADIO" } } } ] } ```

We can see that

  1. 2024-10-02T07:00:00+01:00 is correctly sent as 20241002/080000, and
  2. HAFAS responds with arrivals/departures without {a,d}TZOffset, so hafas-client interprets them with Europe/Berlin.

possible solutions

First: Maybe there is a simple way to get HAFAS to behave like we want, e.g. upgrading to a newer protocol version?

We still haven't found out if we're just sending wrong requests to HAFAS or HAFAS responds with wrong responses. @Treinfan To investigate this thoroughly, you could

  1. find a route that, on a specific day, only runs until a certain (wall clock) time;
  2. use the local transport provider's website to make sure it returns connections according to the schedule you found;
  3. using db-rest, request journeys for that from/to/departure, to see what HAFAS returns – Make sure to pick a departure just before the last (second-last?) possible journey, to make sure that subsequent (wrong) journeys would still be within the results.

If you do get (seemingly) wrong journeys back from db-rest, try to vary from/to/departure to see when the problem occurs.

Good luck!

Treinfan commented 1 month ago

TL;DR: the responses are correct, the requests should be changed

Yes, I can find such a schedule to help investigating this issue. Let's go for a travel advice from Crewe (7000616) to Inverness (7001204), with a date in the future (12th of December 2024). The local timezone is at that moment UTC+0. There is the daily Caledonian sleeper (a night train) that normally departs 23:45 local time from Crewe and arrives in Inverness 08:45 local time the next day. See the normal timetable of the operator. On the 12th of December a small change to the timetable applies, as Realtime Trains indicate: the departure time in Crewe will be 23:50 (local time) and the arrival time in Inverness 08:35 (local time). For now this seems not to be processed in the Hafas dataset, but those small changes may appear later.

Specifying departure time 23:12 + 02:00 (current timezone in Germany, now it is still daylight saving time) or Specifying departure time 23:12 + 01:00 (timezone in Germany on December 12th) shows the Caledonian Sleeper with the correct time and timezone (departure 23:45 +00:00 and arrival 08:45 +00:00).

                    "plannedDeparture": "2024-12-12T23:45:00Z",
                    "departureDelay": null,
                    "arrival": "2024-12-13T08:45:00Z",
                    "plannedArrival": "2024-12-13T08:45:00Z",
                    "arrivalDelay": null,
                    "reachable": true,
                    "tripId": "2|#VN#1#ST#1727296536#PI#0#ZI#196448#TA#0#DA#121224#1S#7001323#1T#2115#LS#7001204#LT#10845#PU#80#RT#1#CA#X70#ZE#5102#ZB#        #PC#2#FR#7001323#FT#2115#TO#7001204#TT#10845#",
                    "line": {
                        "type": "line",
                        "id": null,
                        "fahrtNr": "5102",
                        "name": null,
                        "public": true,
                        "adminCode": "70CS-C",
                        "mode": "train",
                        "product": "regionalExpress",
                        "operator": {
                            "type": "operator",
                            "id": "caledonian-sleeper",
                            "name": "Caledonian Sleeper"
                        }
                    },

Specifying departure time 23:12 + 00:00 (timezone in UK on December 12th). The Caledonian Sleeper is not visible (but it should be). The first advice starts with a bus departing at 00:44:

                    "departure": "2024-12-13T00:44:00Z",
                    "plannedDeparture": "2024-12-13T00:44:00Z",
                    "departureDelay": null,
                    "arrival": "2024-12-13T01:59:00Z",
                    "plannedArrival": "2024-12-13T01:59:00Z",
                    "arrivalDelay": null,
                    "reachable": true,
                    "tripId": "2|#VN#1#ST#1727296536#PI#0#ZI#200695#TA#0#DA#131224#1S#7000616#1T#44#LS#7001537#LT#159#PU#80#RT#1#CA#Bsv#ZE#56119#ZB#Bus56119#PC#3#FR#7000616#FT#44#TO#7001537#TT#159#",
                    "line": {
                        "type": "line",
                        "id": "bus56119",
                        "fahrtNr": "56119",
                        "name": "Bus56119",
                        "public": true,
                        "adminCode": "70NT-S",
                        "productName": "Bus",
                        "mode": "train",
                        "product": "regional",
                        "operator": {
                            "type": "operator",
                            "id": "northern",
                            "name": "Northern"
                        }
                    },

Specifying departure time 22:12 + 00:00 (timezone in UK on December 12th) Just to verifiy that the caledonian sleeper is shown if I specify a departure time one hour earlier:

                    "departure": "2024-12-12T23:45:00Z",
                    "plannedDeparture": "2024-12-12T23:45:00Z",
                    "departureDelay": null,
                    "arrival": "2024-12-13T08:45:00Z",
                    "plannedArrival": "2024-12-13T08:45:00Z",
                    "arrivalDelay": null,
                    "reachable": true,
                    "tripId": "2|#VN#1#ST#1727296536#PI#0#ZI#196448#TA#0#DA#121224#1S#7001323#1T#2115#LS#7001204#LT#10845#PU#80#RT#1#CA#X70#ZE#5102#ZB#        #PC#2#FR#7001323#FT#2115#TO#7001204#TT#10845#",
                    "line": {
                        "type": "line",
                        "id": null,
                        "fahrtNr": "5102",
                        "name": null,
                        "public": true,
                        "adminCode": "70CS-C",
                        "mode": "train",
                        "product": "regionalExpress",
                        "operator": {
                            "type": "operator",
                            "id": "caledonian-sleeper",
                            "name": "Caledonian Sleeper"
                        }
                    },
Treinfan commented 1 month ago

I just have updated my previous reply with all examples. It seems that the returned timetable is fully correct, so probably the requests should be changed to solve the time difference between what I want to request and what is returned.