Skip to content

Commit 861470a

Browse files
authored
Merge pull request #1189 from ascholerChemeketa/canvas-tz-fix
LTI1p3: update timezone handling to accomodate Canvas change
2 parents 3122876 + a1563c1 commit 861470a

1 file changed

Lines changed: 28 additions & 4 deletions

File tree

  • bases/rsptx/admin_server_api/routers

bases/rsptx/admin_server_api/routers/lti1p3.py

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import uuid
2323
import os
2424
import tldextract
25+
from zoneinfo import ZoneInfo
2526

2627
# Third-party imports
2728
# -------------------
@@ -42,6 +43,7 @@
4243
# -------------------
4344
from rsptx.db.models import (
4445
AuthUserValidator,
46+
Courses,
4547
CoursesValidator,
4648
Lti1p3Conf,
4749
Lti1p3User,
@@ -461,7 +463,7 @@ async def launch(request: Request):
461463
# make sure RS assignment is up to date (e.g. end date)
462464
course_attributes = await fetch_all_course_attributes(course.id)
463465
await update_rsassignment_from_lti(
464-
rs_assign, assign_lineitem, course_attributes
466+
rs_assign, assign_lineitem, course_attributes, course
465467
)
466468

467469
# start redirect to assignment
@@ -508,14 +510,34 @@ async def update_lti_assignment_record(
508510

509511

510512
async def update_rsassignment_from_lti(
511-
assign: AssignmentValidator, line_item: LineItem, course_attributes: dict
513+
assign: AssignmentValidator,
514+
line_item: LineItem,
515+
course_attributes: dict,
516+
course: Courses,
512517
) -> AssignmentValidator:
513518
"""
514519
Update a runestone assignment from LTI data.
515520
"""
516521
try:
517522
lms_due_string = line_item.get_end_date_time()
518-
lms_due = datetime.datetime.fromisoformat(lms_due_string)
523+
rslogger.info(
524+
f"LTI1p3 - Received {lms_due_string} for assignment {assign.name}"
525+
)
526+
527+
# Parse ISO datetime. Normalize trailing Z so fromisoformat can parse UTC.
528+
normalized_due_string = (
529+
lms_due_string.replace("Z", "+00:00")
530+
if lms_due_string.endswith("Z")
531+
else lms_due_string
532+
)
533+
lms_due = datetime.datetime.fromisoformat(normalized_due_string)
534+
535+
# If LMS provided timezone info and course has a timezone, convert to course local time.
536+
if lms_due.tzinfo is not None and course.timezone:
537+
lms_due = lms_due.astimezone(ZoneInfo(course.timezone))
538+
rslogger.info(
539+
f"LTI1p3 - Converted to {lms_due} in timezone {course.timezone}"
540+
)
519541
lms_due = lms_due.replace(tzinfo=None)
520542
if (
521543
lms_due is not None
@@ -1125,7 +1147,9 @@ async def assign_select(launch_id: str, request: Request, course=None):
11251147
)
11261148
await ags.update_lineitem(line_item)
11271149
# update RS due date
1128-
await update_rsassignment_from_lti(assign, line_item, course_attributes)
1150+
await update_rsassignment_from_lti(
1151+
assign, line_item, course_attributes, course
1152+
)
11291153
deep_link = message_launch.get_deep_link()
11301154
response_html = deep_link.output_response_form(response_list)
11311155
response = HTMLResponse(content=response_html, status_code=200)

0 commit comments

Comments
 (0)