Handle short European trips with rail/ferry returns

When traveling to nearby European countries by rail or ferry,
return journeys often aren't recorded in flight/accommodation
data. Added logic to assume you've returned home after short
European trips that ended >3 days ago.

Covers common rail/ferry destinations: Belgium, Netherlands,
France, Germany, Switzerland, Austria, Italy, Spain.

Example: Feb 2-5 trip to Brussels (by rail), Feb 18 now
correctly shows "Bristol" instead of "Brussels".

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Edward Betts 2025-07-16 04:28:15 +02:00
parent 6533165bef
commit 80e12b77ce
2 changed files with 68 additions and 16 deletions

View file

@ -86,7 +86,7 @@ def get_location_for_date(
trips: list[Trip], trips: list[Trip],
bookings: list[dict], bookings: list[dict],
accommodations: list[dict], accommodations: list[dict],
airports: dict airports: dict,
) -> tuple[str, pycountry.db.Country | None]: ) -> tuple[str, pycountry.db.Country | None]:
"""Get location (city, country) for a specific date using travel history.""" """Get location (city, country) for a specific date using travel history."""
# UK airports that indicate being home # UK airports that indicate being home
@ -118,10 +118,17 @@ def get_location_for_date(
# Only consider flights within this trip and before target date # Only consider flights within this trip and before target date
if trip.start <= arrive_date <= target_date: if trip.start <= arrive_date <= target_date:
# Compare both date and time to handle same-day flights correctly # Compare both date and time to handle same-day flights correctly
if (trip_most_recent_date is None or if (
arrive_date > trip_most_recent_date or trip_most_recent_date is None
(arrive_date == trip_most_recent_date and or arrive_date > trip_most_recent_date
(trip_most_recent_datetime is None or arrive_datetime > trip_most_recent_datetime))): or (
arrive_date == trip_most_recent_date
and (
trip_most_recent_datetime is None
or arrive_datetime > trip_most_recent_datetime
)
)
):
trip_most_recent_date = arrive_date trip_most_recent_date = arrive_date
trip_most_recent_datetime = arrive_datetime trip_most_recent_datetime = arrive_datetime
@ -211,10 +218,17 @@ def get_location_for_date(
if arrive_date <= target_date: if arrive_date <= target_date:
# Compare both date and time to handle same-day flights correctly # Compare both date and time to handle same-day flights correctly
if (most_recent_date is None or if (
arrive_date > most_recent_date or most_recent_date is None
(arrive_date == most_recent_date and or arrive_date > most_recent_date
(most_recent_datetime is None or arrive_datetime > most_recent_datetime))): or (
arrive_date == most_recent_date
and (
most_recent_datetime is None
or arrive_datetime > most_recent_datetime
)
)
):
most_recent_date = arrive_date most_recent_date = arrive_date
most_recent_datetime = arrive_datetime most_recent_datetime = arrive_datetime
@ -264,14 +278,31 @@ def get_location_for_date(
# If so, prioritize that over foreign accommodations within the trip # If so, prioritize that over foreign accommodations within the trip
if most_recent_location and most_recent_date: if most_recent_location and most_recent_date:
for trip in trips: for trip in trips:
if (trip.end and trip.end < target_date and if (
trip.start <= most_recent_date <= trip.end): trip.end
and trip.end < target_date
and trip.start <= most_recent_date <= trip.end
):
# The most recent travel was within a trip that has since ended # The most recent travel was within a trip that has since ended
locations = trip.locations() locations = trip.locations()
if locations: if locations:
final_city, final_country = locations[-1] final_city, final_country = locations[-1]
# If trip ended in UK, you should be home now # If trip ended in UK, you should be home now
if hasattr(final_country, 'alpha_2') and final_country.alpha_2 == 'GB': if (
hasattr(final_country, "alpha_2")
and final_country.alpha_2 == "GB"
):
return ("Bristol", get_country("gb"))
# For short European trips (ended >3 days ago), assume returned home
# if no subsequent travel data shows you're still abroad
days_since_trip = (target_date - trip.end).days
if (
days_since_trip > 3
and hasattr(final_country, "alpha_2")
and final_country.alpha_2
in {"BE", "NL", "FR", "DE", "CH", "AT", "IT", "ES"}
):
return ("Bristol", get_country("gb")) return ("Bristol", get_country("gb"))
# Return most recent location or default to Bristol # Return most recent location or default to Bristol
@ -314,8 +345,12 @@ def weekends(
if event.end_date and event.as_date <= sunday <= event.end_as_date if event.end_date and event.as_date <= sunday <= event.end_as_date
] ]
saturday_location = get_location_for_date(saturday, trips, bookings, accommodations, airports) saturday_location = get_location_for_date(
sunday_location = get_location_for_date(sunday, trips, bookings, accommodations, airports) saturday, trips, bookings, accommodations, airports
)
sunday_location = get_location_for_date(
sunday, trips, bookings, accommodations, airports
)
weekends_info.append( weekends_info.append(
{ {

View file

@ -13,9 +13,16 @@ def test_get_location_for_date() -> None:
trips = [ trips = [
t t
for t in agenda.trip.build_trip_list() for t in agenda.trip.build_trip_list()
if t.start in [date(2023, 9, 8), date(2023, 11, 14), date(2025, 2, 9)] if t.start
in [
date(2023, 2, 2),
date(2023, 9, 8),
date(2023, 11, 14),
date(2025, 2, 9),
date(2025, 7, 4),
]
] ]
assert len(trips) == 3 assert len(trips) == 5
data_dir = app.config["PERSONAL_DATA"] data_dir = app.config["PERSONAL_DATA"]
@ -43,3 +50,13 @@ def test_get_location_for_date() -> None:
date(2023, 10, 7), trips, bookings, accommodations, airports date(2023, 10, 7), trips, bookings, accommodations, airports
) )
assert l2[0] == "Bristol" assert l2[0] == "Bristol"
l2 = agenda.busy.get_location_for_date(
date(2023, 2, 18), trips, bookings, accommodations, airports
)
assert l2[0] == "Bristol"
l2 = agenda.busy.get_location_for_date(
date(2025, 8, 2), trips, bookings, accommodations, airports
)
assert l2[0] == "Bristol"