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 <>
parent 6767bded
from zoneinfo import ZoneInfo
from django.conf import settings
from 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.'
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 < + datetime.timedelta(days=14):
self.stdout.write('Successfully created 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 < + 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.stdout.write("Successfully created events")
def update_event(self, event):
delta = datetime.timedelta(days=event.delay)
def update_rec_event(self, rec_event: RecurrentEvent) -> None:
delta = datetime.timedelta(days=rec_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']]})
if rec_event.last_created is None: # First creation
e = rec_event.create_instance()
event.last_created = e.start_time
self.stdout.write("First creation of %s, start = %s (delay=%d)" % (event, event.start_time, event.delay))
rec_event.last_created = e.start_time
f"First creation of {rec_event}, "
f"start = {rec_event.start_time} "
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(
e.end_time = e.end_time.astimezone(localtz).replace(
e.end_inscriptions = e.end_inscriptions.astimezone(localtz).replace(
if e.invitations_start is not None:
e.invitations_start = e.invitations_start.astimezone(
self.stdout.write("Creating event %s for date %s" % (event, event.last_created))
rec_event.last_created = e.start_time
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
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