@@ -88,6 +88,15 @@ def get_events_year(year: int) -> tuple[Response, int]:
8888 return jsonify ([event .to_dict () for event in events ]), 200
8989
9090
91+ def get_duration_from_string (duration_str : str ) -> timedelta | str :
92+ """Convert a duration string in the format 'days:hours:minutes' to a timedelta."""
93+ try :
94+ days , hours , minutes = map (int , duration_str .split (":" ))
95+ return timedelta (days = days , hours = hours , minutes = minutes )
96+ except ValueError :
97+ return "Invalid duration format, expected 'days:hours:minutes'"
98+
99+
91100@events_api_bp .route ("/create" , methods = ["POST" ])
92101@is_exec_wrapper
93102def create_event_api () -> tuple [Response , int ]:
@@ -111,16 +120,9 @@ def create_event_api() -> tuple[Response, int]:
111120 datetime .fromisoformat (data ["start_time" ])
112121 )
113122 if "duration" in data :
114- try :
115- days , hours , minutes = map (int , data ["duration" ].split (":" ))
116- duration = timedelta (days = days , hours = hours , minutes = minutes )
117- except ValueError :
118- return (
119- jsonify (
120- {"error" : "Invalid duration format, expected 'days:hours:minutes'" }
121- ),
122- 400 ,
123- )
123+ duration = get_duration_from_string (data ["duration" ])
124+ if isinstance (duration , str ):
125+ return jsonify ({"error" : duration }), 400
124126 else :
125127 duration = None
126128
@@ -212,15 +214,18 @@ def get_week_from_date(date: datetime) -> Week | None:
212214 # fetch the term dates from the Warwick API
213215
214216 warwick_week = requests .get (
215- f"https://tabula.warwick.ac.uk/api/v1/termdates/{ year } /weeks?numberingSystem=term"
217+ f"https://tabula.warwick.ac.uk/api/v1/termdates/{ year } /weeks?numberingSystem=term" ,
218+ timeout = 5 ,
216219 ).json ()
217220
218221 for w in warwick_week ["weeks" ]:
219- if (
220- datetime .strptime (w ["startDate" ], "%Y-%m-%d" ).date ()
221- <= date .date ()
222- <= datetime .strptime (w ["endDate" ], "%Y-%m-%d" ).date ()
223- ):
222+ start_date = datetime .strptime (w ["startDate" ], "%Y-%m-%d" ).replace (
223+ tzinfo = pytz .timezone ("Europe/London" )
224+ )
225+ end_date = datetime .strptime (w ["endDate" ], "%Y-%m-%d" ).replace (
226+ tzinfo = pytz .timezone ("Europe/London" )
227+ )
228+ if start_date .date () <= date .date () <= end_date .date ():
224229 name = w ["name" ]
225230 if "Term" in name :
226231 parts = name .split ("," )
@@ -234,7 +239,7 @@ def get_week_from_date(date: datetime) -> Week | None:
234239 academic_year = year ,
235240 term = term_num ,
236241 week = week_num ,
237- start_date = datetime . strptime ( w [ "startDate" ], "%Y-%m-%d" ) ,
242+ start_date = start_date ,
238243 )
239244
240245 db .session .add (week )
@@ -245,12 +250,15 @@ def get_week_from_date(date: datetime) -> Week | None:
245250 with Path ("olddates.json" ).open ("r" ) as f :
246251 old_dates = load (f )
247252 for w in old_dates :
248- if datetime .strptime (w ["date" ], "%Y-%m-%d" ).date () <= date .date ():
253+ start_date = datetime .strptime (w ["start_date" ], "%Y-%m-%d" ).replace (
254+ tzinfo = pytz .timezone ("Europe/London" )
255+ )
256+ if start_date .date () <= date .date ():
249257 week = Week (
250258 academic_year = year ,
251259 term = w ["term" ],
252260 week = w ["week" ],
253- start_date = datetime . strptime ( w [ "date" ], "%Y-%m-%d" ) ,
261+ start_date = start_date ,
254262 )
255263 db .session .add (week )
256264 db .session .commit ()
@@ -279,16 +287,11 @@ def create_repeat_event_api() -> tuple[Response, int]: # noqa: PLR0911
279287 return jsonify ({"error" : f"Missing required field: { field } " }), 400
280288
281289 if "duration" in data :
282- try :
283- days , hours , minutes = map (int , data ["duration" ].split (":" ))
284- duration = timedelta (days = days , hours = hours , minutes = minutes )
285- except ValueError :
286- return (
287- jsonify (
288- {"error" : "Invalid duration format, expected 'days:hours:minutes'" }
289- ),
290- 400 ,
291- )
290+ duration = get_duration_from_string (data ["duration" ])
291+ if isinstance (duration , str ):
292+ return jsonify ({"error" : duration }), 400
293+ else :
294+ duration = None
292295
293296 start_times = []
294297 for start_time_str in data ["start_times" ]:
@@ -406,18 +409,10 @@ def edit_event(event_id: int) -> tuple[Response, int]:
406409 datetime .fromisoformat (data .get ("start_time" , event .start_time .isoformat ()))
407410 )
408411 if "duration" in data :
409- try :
410- days , hours , minutes = map (int , data ["duration" ].split (":" ))
411- event .duration = timedelta (days = days , hours = hours , minutes = minutes )
412- except ValueError :
413- return (
414- jsonify (
415- {
416- "error" : "Invalid duration format, expected 'days:hours:minutes'"
417- }
418- ),
419- 400 ,
420- )
412+ duration = get_duration_from_string (data ["duration" ])
413+ if isinstance (duration , str ):
414+ return jsonify ({"error" : duration }), 400
415+ event .end_time = event .start_time + duration
421416
422417 # update week if start_time has changed
423418 if "start_time" in data :
0 commit comments