Verified Commit 220d86d2 authored by VAN ZUIJLEN Nils's avatar VAN ZUIJLEN Nils
Browse files

Fix timezone-related bug in RecurrentEvents

Use local timezone to fix the hour to a certain value

Fixes #71

Signed-off-by: VAN ZUIJLEN Nils's avatarNils VAN ZUIJLEN <nils.van-zuijlen@mailo.com>
parent 6767bded
from zoneinfo import ZoneInfo
from django.conf import settings
from django.core.management.base import BaseCommand
from events.models import RecurrentEvent, Event
from django.utils import timezone
import datetime
from events.models import RecurrentEvent
class Command(BaseCommand):
help = 'Create events based on recurrent events.'
def handle(self, *args, **options):
for event in RecurrentEvent.objects.all():
while True:
if event.last_created is None or event.last_created < timezone.now() + datetime.timedelta(days=14):
self.update_event(event)
else:
break
self.stdout.write('Successfully created events')
def update_event(self, event):
delta = datetime.timedelta(days=event.delay)
if event.last_created is None: # First creation
e = Event.objects.create(**{field: value for field, value in event.__dict__.items() if field in [field.column for field in Event._meta.fields if field.column not in ['id', 'model']]})
help = "Create events based on recurrent events."
def handle(self, *args, **options) -> None:
"""Create instances for recurrent events for at least the next 14 days"""
for rec_event in RecurrentEvent.objects.all():
while (
rec_event.last_created is None # Première création
or rec_event.last_created < timezone.now() + datetime.timedelta(days=14)
):
# Tant que la dernière instance de l'évenement est
# dans moins de 14 jours
# Créer une nouvelle instance
self.update_rec_event(rec_event)
self.stdout.write("Successfully created events")
def update_rec_event(self, rec_event: RecurrentEvent) -> None:
delta = datetime.timedelta(days=rec_event.delay)
if rec_event.last_created is None: # First creation
e = rec_event.create_instance()
e.save()
event.last_created = e.start_time
event.save()
self.stdout.write("First creation of %s, start = %s (delay=%d)" % (event, event.start_time, event.delay))
rec_event.last_created = e.start_time
rec_event.save()
self.stdout.write(
f"First creation of {rec_event}, "
f"start = {rec_event.start_time} "
f"(delay={rec_event.delay})"
)
else:
delta_dates = event.last_created - event.start_time + delta
e = Event.objects.create(**{field: value for field, value in event.__dict__.items() if field in [field.column for field in Event._meta.fields if field.column not in ['id', 'model']]})
delta_dates = rec_event.last_created - rec_event.start_time + delta
e = rec_event.create_instance()
e.start_time += delta_dates
e.start_time = e.start_time.replace(hour=event.start_time.hour)
event.last_created = e.start_time
e.end_time += delta_dates
e.end_time = e.end_time.replace(hour=event.end_time.hour)
e.end_inscriptions += delta_dates
e.end_inscriptions = e.end_inscriptions.replace(hour=event.end_inscriptions.hour)
if e.invitations_start is not None:
e.invitations_start += delta_dates
e.invitations_start = e.invitations_start.replace(hour=event.invitations_start.hour)
if settings.USE_TZ:
# If we use timezones, fix the hours in the local timezone
localtz = ZoneInfo(settings.TIME_ZONE)
e.start_time = e.start_time.astimezone(localtz).replace(
hour=rec_event.start_time.astimezone(localtz).hour
)
e.end_time = e.end_time.astimezone(localtz).replace(
hour=rec_event.end_time.astimezone(localtz).hour
)
e.end_inscriptions = e.end_inscriptions.astimezone(localtz).replace(
hour=rec_event.end_inscriptions.astimezone(localtz).hour
)
if e.invitations_start is not None:
e.invitations_start = e.invitations_start.astimezone(
localtz
).replace(hour=rec_event.invitations_start.astimezone(localtz).hour)
e.save()
event.save()
self.stdout.write("Creating event %s for date %s" % (event, event.last_created))
rec_event.last_created = e.start_time
rec_event.save()
self.stdout.write(
f"Creating event {rec_event} for date {rec_event.last_created}"
)
......@@ -126,7 +126,7 @@ class Event(models.Model):
class RecurrentEvent(Event):
delay = models.IntegerField(default=1)
delay = models.IntegerField(default=1) # In days
last_created = models.DateTimeField(null=True, blank=True, default=None)
class Meta:
......@@ -134,6 +134,21 @@ class RecurrentEvent(Event):
('manage_recurrent_event', 'Can manage recurrent event (add/del/edit'),
)
def create_instance(self) -> Event:
"""Create an Event instance of the RecurrentEvent"""
return Event.objects.create(
**{
field: value
for field, value in self.__dict__.items()
if field
in { # Use sets for faster `in` checks
field.column
for field in Event._meta.fields
if field.column not in {"id", "model"}
}
}
)
class ExternLink(models.Model):
event = models.ForeignKey(Event, related_name="extern_links", on_delete=models.CASCADE)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment