Rescheduling Events
“Just cancel the old ones and book new ones.”
Here are some challenges I faced.
I recently built a rescheduling engine for multi-part bookings (like consult + treatment) with constraints like:
- user availability
- event durations
- time conflicts
- step order (e.g., numbing must come before injection)
Problem 1: Greedy Scheduling Fails Fast #
At first, I reached for a simple greedy strategy:
sorted_slots = sorted(slots)
selected = sorted_slots[:3]
It worked for one event. But chaining two?
Step 1: 10:00–10:30
Step 2: 10:15–10:45 ← Overlaps!
Sometimes step 2 came before step 1. Other times, an “available” slot wasn’t actually bookable due to stale data.
Fix: Use a Sliding Window Matcher #
def find_valid_chains(slots_list, durations):
chains = []
for i in range(len(slots_list[0])):
chain = [slots_list[0][i]]
valid = True
for j in range(1, len(slots_list)):
next_slot = next((
s for s in slots_list[j]
if s >= chain[-1] + timedelta(minutes=durations[j-1])
), None)
if not next_slot:
valid = False
break
chain.append(next_slot)
if valid:
chains.append(chain)
return chains
Now, all steps occur in the right order without overlaps.
Problem 2: Time Zones Break Everything #
One day, all the times looked correct. The next? Off by 8 hours.
Turns out the API gave me UTC timestamps, but my app logic compared them to local time (like 10:00am in GMT+8).
Fix: Normalize All Timezones #
from datetime import timezone, timedelta
slot_dt = datetime.fromisoformat(slot.replace("Z", "+00:00"))
local_dt = slot_dt.astimezone(timezone(timedelta(hours=8)))
Lesson: never compare datetime strings directly. Always use timezone-aware datetime.
Problem 3: Updating Isn’t Always Allowed #
I assumed I could reschedule by modifying the original event. Sometimes, the API silently failed or returned errors for:
- locked events
- past events
- already modified records
What I Had to Do Instead #
If update fails:
try:
update_event()
except HttpError as e:
cancel_old()
create_new()
Yep, sometimes rescheduling means cancel and recreate.
Comparing Algorithms #
| Strategy | Outcome |
|---|---|
| Greedy | Fast but fails with multiple steps |
| Backtracking + Constraints | Works but slow, too many combinations |
| Sliding Window | Fast, respects order, easy to debug |
Sliding Window gave the best tradeoff between correctness and speed.
Bonus: Graph-Based Scheduling #
I experimented with modeling slots as a graph:
- Each node = a time slot
- Edge = valid time gap between steps
This enabled basic pathfinding with BFS:
paths = bfs(start_slot, goal_condition)
It’s overkill for most cases, but cool when scheduling across multiple days or optimizing for least wait time.
Final Thoughts #
What I learned building this:
- APIs are messy. Slots might be stale, out-of-sync, or conflict-prone.
- Timezones can be an oversight.
- Harder than I thought!