Skip to content

Commit

Permalink
fix event copy timezone issues
Browse files Browse the repository at this point in the history
  • Loading branch information
felixrindt authored and jeriox committed Apr 4, 2024
1 parent 54e4fb7 commit e111581
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 20 deletions.
41 changes: 22 additions & 19 deletions ephios/core/views/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -393,8 +393,10 @@ def _build_day_css_context(self, events, shifts):
earliest_shift_start = min(shift.start_time for shift in shifts)
latest_shift_end = max(shift.end_time for shift in shifts)
# calculate timescale based on shortest shift
# to not make things too small, consider a maximum of 4 hours
shortest_shift_duration_in_hours = min(4, shortest_shift_duration.total_seconds() / 3600)
# to not make things too small, consider a maximum of 4 hours and a minimum of 15 minutes
shortest_shift_duration_in_hours = max(
0.25, min(4, shortest_shift_duration.total_seconds() / 3600)
)
# seconds per em: the shortest shift should be 3600/300 = 12em high
time_scaling_factor = int(300 * shortest_shift_duration_in_hours)
for shift in shifts:
Expand Down Expand Up @@ -541,6 +543,7 @@ def setup(self, request, *args, **kwargs):
self.object = self.get_object()

def form_valid(self, form):
tz = get_current_timezone()
occurrences = form.cleaned_data["recurrence"].between(
datetime.now() - timedelta(days=1),
datetime.now() + timedelta(days=7305), # allow dates up to twenty years in the future
Expand All @@ -551,7 +554,7 @@ def form_valid(self, form):
)
for date in occurrences:
event = self.get_object()
start_date = event.get_start_time().date()
start_date = event.get_start_time().astimezone(tz).date()
shifts = list(event.shifts.all())
event.pk = None
event.save()
Expand Down Expand Up @@ -579,25 +582,25 @@ def form_valid(self, form):
for shift in shifts:
shift.pk = None
# shifts on following days should have the same offset from the new date
offset = shift.start_time.date() - start_date
offset = shift.start_time.astimezone(tz).date() - start_date
# shifts ending on the next day should end on the next day to the new date
end_offset = shift.end_time.date() - shift.start_time.date()
current_tz = get_current_timezone()
shift.end_time = make_aware(
datetime.combine(
date.date() + offset + end_offset,
shift.end_time.astimezone(current_tz).time(),
)
end_offset = (
shift.end_time.astimezone(tz).date() - shift.start_time.astimezone(tz).date()
)
shift.meeting_time = make_aware(
datetime.combine(
date.date() + offset, shift.meeting_time.astimezone(current_tz).time()
)
shift.meeting_time = datetime.combine(
date.date() + offset,
shift.meeting_time.astimezone(tz).time(),
tzinfo=tz,
)
shift.start_time = make_aware(
datetime.combine(
date.date() + offset, shift.start_time.astimezone(current_tz).time()
)
shift.start_time = datetime.combine(
date.date() + offset,
shift.start_time.astimezone(tz).time(),
tzinfo=tz,
)
shift.end_time = datetime.combine(
date.date() + offset + end_offset,
shift.end_time.astimezone(tz).time(),
tzinfo=tz,
)
shift.event = event
shifts_to_create.append(shift)
Expand Down
33 changes: 32 additions & 1 deletion tests/core/test_event_copy.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from datetime import datetime, timedelta
from datetime import datetime, time, timedelta

import recurrence
from django.urls import reverse
from django.utils import timezone
from guardian.shortcuts import assign_perm

from ephios.core.models import Event, Shift
Expand Down Expand Up @@ -145,3 +146,33 @@ def test_event_to_next_day_copy(self, django_app, planner, event_to_next_day, gr
assert planners in get_groups_with_perms(
shift.event, only_with_perms_in=["change_event"]
)

def test_copy_overnight_event_with_times_close_to_midnight(
self, django_app, planner, event, tz
):
original_shift = event.shifts.first()
original_shift.start_time = datetime.combine(
original_shift.start_time.date(), time(hour=23, minute=30), tzinfo=tz
)
original_shift.end_time = datetime.combine(
original_shift.start_time.date() + timedelta(days=1), time(hour=0, minute=30), tzinfo=tz
)
original_shift.save()
response = django_app.get(reverse("core:event_copy", kwargs={"pk": event.id}), user=planner)
form = response.form
target_starttime = timezone.now() + timedelta(days=14)
recurr = recurrence.Recurrence(
dtstart=target_starttime,
rdates=[],
)
form["start_date"] = target_starttime.date()
form["recurrence"] = str(recurr)
form.submit()
copied_shift = Shift.objects.exclude(event=event).get()
assert copied_shift.start_time.astimezone(tz).date() == target_starttime.date()
assert copied_shift.start_time.astimezone(tz).time() == original_shift.start_time.time()
assert (
copied_shift.end_time.astimezone(tz).date()
== (target_starttime + timedelta(days=1)).date()
)
assert copied_shift.end_time.astimezone(tz).time() == original_shift.end_time.time()

0 comments on commit e111581

Please sign in to comment.