Fix scheduled stop times at 24:00 and later when building bus_stop_time - #32
Open
eastagiletracker wants to merge 1 commit into
Open
eastagiletracker wants to merge 1 commit into
eastagiletracker wants to merge 1 commit into
Conversation
Schedule times of 24:00:00 and later belong to the previous service day. dedupe_schedules rewrote the hour in place with a substring replace, which also rewrote a minute or second of "24" in the same value, and left hours of 25 and above unparseable so they were coerced to NaT. Build bus_stop_time by adding the stop time to the service date instead, so the extra hours roll into the date and the rest of the value is untouched.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR proposes a fix for the scheduled stop times at 24:00:00 and later that
dedupe_scheduleswrites intodata/clean_timetables, so hours past midnight roll into the service date instead of being rewritten in place (Fixes #21). We include this PR work along with a full history of your repo at https://eastagiletracker.com/projects/500. You can sign in with your GitHub ID to claim ownership of the project.What happens today
report_automation/update_schedule.pybuildsbus_stop_timefrom the GTFS service date andarrival_time, rewriting the hour in place for times that start with24:Series.str.replacedefaults toregex=Falseand replaces every occurrence rather than just the hour, so a value whose minutes or seconds are also24loses them. Separately,25:XX:XXnever matches the== "24"test at all, so it reachespd.to_datetime(..., errors="coerce")as an unparseable string and lands asNaT.Running that expression verbatim at
7a4e554onmain, overarrival_timevalues taken from the current CTAgoogle_transit.zip:In that feed (fetched 2026-08-06) 50,938
stop_timesrows carry an hour of24. Of those, 1,685 also have24in the minutes or the seconds and silently lose it —24:24:00becomes midnight rather than 00:24. A further 728 rows at hour25becomeNaT. TheNaThalf is already worked around twice in the repo: the comment you left at the assignment, and theis_not_nullfilter inmetrics_utils.create_trips_dfthat drops schedule rows with nobus_stop_time. The minutes-and-seconds half is not guarded anywhere, because a mangled value is still a perfectly well-formed timestamp.On blast radius, so the tradeoff is clear rather than oversold:
stop_metrics.time_to_next_stopdefaults tois_daytime=Trueand keeps only hours 6 to 20, so none of these rows reach the published metrics as things stand. What does change isdata/clean_timetables/*.parquetitself. It is written withdateandarrival_timedropped, sobus_stop_timeis the only surviving time value — the wrong times are permanent in the archive you publish and push to S3, and cannot be reconstructed later. That is also what makes the late-night window unusable the momentis_daytimeis turned off.The change
build_bus_stop_timeadds the stop time to the service date as an offset instead of editing the hour text:pd.to_timedeltaalready understands GTFS hours past 24, so24:06:24and25:08:00roll into the next day with their minutes and seconds intact, ordinary times are untouched, and missing or unparseable values still becomeNaTexactly as before. Thetime_editanddate_editcolumns are now dead, so they come out of thedroplist, and thenumpyimport goes with them sincenp.wherewas its only use in the module.I left the
is_not_nullfilter inmetrics_utils.create_trips_dfalone. It no longer has anything to drop from this cause, but it is still a reasonable guard and removing it would change behavior you may want for other reasons.Verification
cta-stop-watch/report_automation/test_update_schedule.pyis new, stdlibunittest, no added dependency. Fromreport_automation/:Five tests cover ordinary times, the hour-24 rollover, the hour-25 rollover, unusable values, and the returned dtype. Against the previous expression the hour-24 and hour-25 tests fail while the three controls stay green; against this change all five pass.
I also ran
dedupe_schedules()itself end to end, over a smallrt21timetable fixture plus an existing historic parquet, on both trees:The historic row outside the current window survived on both sides and the column drop still succeeds, so the merge with
data/clean_timetablesis unchanged. The repo ships no test or CI configuration, so for a before/after comparison I usedcompileallplus an import of every module inreport_automation: identical on both trees, includingupdate_metricsfailing itsmemory_profilerimport the same way each time. That one is unrelated to this change —memory_profileris imported but not declared inpyproject.toml— so I left it alone rather than folding it in here.How this was managed
We imported this repository's issues and pull requests onto a live agile board — 31 stories — and used it to manage this work. The story this PR delivers is fixing time in schedule past 1am, and the board it sits on is at https://eastagiletracker.com/projects/500.
If you'd rather not receive contributions like this, reply
no-more-prson this pull request and we won't open any further ones on your repositories.Lawrence W. Sinclair
CEO / East Agile
linkedin.com/in/lwsinclair/
eastagile.com