Skip to content

Commit

Permalink
Store event start and end as datetimes instead of str (#246)
Browse files Browse the repository at this point in the history
* Store event start and end datetimes as datetimes instead of str.

This removes the need for the date.isoformat(), and then immediately call an expensive parse on the string during the availability route.

* Don't convert datetimes to strings on event creation for caldav.

* Do convert datetimes to strings on event creation for google calendar...
  • Loading branch information
MelissaAutumn authored Jan 26, 2024
1 parent e1e56b5 commit d6a0071
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 22 deletions.
27 changes: 14 additions & 13 deletions backend/src/appointment/controller/calendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ def list_events(self, start, end):

all_day = "date" in event.get("start")

start = event.get("start")["date"] if all_day else event.get("start")["dateTime"]
end = event.get("end")["date"] if all_day else event.get("end")["dateTime"]
start = datetime.strptime(event.get("start")["date"], DATEFMT) if all_day else datetime.fromisoformat(event.get("start")["dateTime"])
end = datetime.strptime(event.get("end")["date"], DATEFMT) if all_day else datetime.fromisoformat(event.get("end")["dateTime"])

events.append(
schemas.Event(
Expand Down Expand Up @@ -128,8 +128,8 @@ def create_event(
"summary": event.title,
"location": event.location.name,
"description": "\n".join(description),
"start": {"dateTime": event.start},
"end": {"dateTime": event.end},
"start": {"dateTime": event.start.isoformat()},
"end": {"dateTime": event.end.isoformat()},
"attendees": [
{"displayName": organizer.name, "email": organizer.email},
{"displayName": attendee.name, "email": attendee.email},
Expand Down Expand Up @@ -194,9 +194,9 @@ def list_events(self, start, end):

events.append(
schemas.Event(
title=str(e.vobject_instance.vevent.summary.value),
start=str(e.vobject_instance.vevent.dtstart.value),
end=str(e.vobject_instance.vevent.dtend.value),
title=e.vobject_instance.vevent.summary.value,
start=e.vobject_instance.vevent.dtstart.value,
end=e.vobject_instance.vevent.dtend.value,
all_day=not isinstance(e.vobject_instance.vevent.dtstart.value, datetime),
tentative=tentative,
description=e.icalendar_component["description"] if "description" in e.icalendar_component else "",
Expand All @@ -214,8 +214,8 @@ def create_event(
calendar = self.client.calendar(url=self.url)
# save event
caldavEvent = calendar.save_event(
dtstart=datetime.fromisoformat(event.start),
dtend=datetime.fromisoformat(event.end),
dtstart=event.start,
dtend=event.end,
summary=event.title,
# TODO: handle location
description=event.description,
Expand Down Expand Up @@ -343,15 +343,16 @@ def events_set_difference(a_list: list[schemas.SlotBase], b_list: list[schemas.E
a_end = a_start + timedelta(minutes=a.duration)
collision_found = False
for b in b_list:
b_start = parse(b.start)
b_end = parse(b.end)
b_start = b.start
b_end = b.end
# if there is an overlap of both date ranges, a collision was found
# see https://en.wikipedia.org/wiki/De_Morgan%27s_laws
if a_start.timestamp() < b_end.timestamp() and a_end.timestamp() > b_start.timestamp():
collision_found = True
break
if not collision_found:
available_slots.append(a)

return available_slots

@staticmethod
Expand Down Expand Up @@ -392,8 +393,8 @@ def existing_events_for_schedule(
for slot in schedule.slots:
existing_events.append(schemas.Event(
title=schedule.name,
start=slot.start.isoformat(),
end=(slot.start + timedelta(minutes=slot.duration)).isoformat(),
start=slot.start,
end=slot.start + timedelta(minutes=slot.duration),
))

return existing_events
4 changes: 2 additions & 2 deletions backend/src/appointment/database/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,8 +268,8 @@ class EventLocation(BaseModel):

class Event(BaseModel):
title: str
start: str
end: str
start: datetime
end: datetime
all_day: bool | None = False
tentative: bool | None = False
description: str | None = None
Expand Down
4 changes: 2 additions & 2 deletions backend/src/appointment/routes/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -400,8 +400,8 @@ def update_public_appointment_slot(

event = schemas.Event(
title=db_appointment.title,
start=slot.start.replace(tzinfo=timezone.utc).isoformat(),
end=(slot.start.replace(tzinfo=timezone.utc) + timedelta(minutes=slot.duration)).isoformat(),
start=slot.start.replace(tzinfo=timezone.utc),
end=slot.start.replace(tzinfo=timezone.utc) + timedelta(minutes=slot.duration),
description=db_appointment.details,
location=schemas.EventLocation(
type=db_appointment.location_type,
Expand Down
4 changes: 2 additions & 2 deletions backend/src/appointment/routes/schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,8 +270,8 @@ def decide_on_schedule_availability_slot(

event = schemas.Event(
title=schedule.name,
start=slot.start.replace(tzinfo=timezone.utc).isoformat(),
end=(slot.start.replace(tzinfo=timezone.utc) + timedelta(minutes=slot.duration)).isoformat(),
start=slot.start.replace(tzinfo=timezone.utc),
end=slot.start.replace(tzinfo=timezone.utc) + timedelta(minutes=slot.duration),
description=schedule.details,
location=schemas.EventLocation(
type=schedule.location_type,
Expand Down
9 changes: 6 additions & 3 deletions backend/test/integration/test_appointment.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import dateutil.parser

from defines import DAY1, DAY2, DAY3, auth_headers


Expand Down Expand Up @@ -392,10 +394,11 @@ def test_get_remote_caldav_events(self, with_client, make_appointment, monkeypat
generated_appointment = make_appointment()

def list_events(self, start, end):
end = dateutil.parser.parse(end)
from appointment.database import schemas
return [schemas.Event(
title=generated_appointment.title,
start=str(generated_appointment.slots[0].start),
start=generated_appointment.slots[0].start,
end=end,
all_day=False,
description=generated_appointment.details,
Expand All @@ -410,8 +413,8 @@ def list_events(self, start, end):
data = response.json()
assert len(data) == 1
assert data[0]["title"] == generated_appointment.title
assert data[0]["start"] == str(generated_appointment.slots[0].start)
assert data[0]["end"] == DAY3
assert data[0]["start"] == generated_appointment.slots[0].start.isoformat()
assert data[0]["end"] == dateutil.parser.parse(DAY3).isoformat()

def test_get_invitation_ics_file(self, with_client, make_appointment):
generated_appointment = make_appointment()
Expand Down

0 comments on commit d6a0071

Please sign in to comment.