Skip to content
Snippets Groups Projects
holidays.py 3.95 KiB
Newer Older
import datetime

from django.core.management.base import BaseCommand

from ...models import Appointment, Location, AppointmentType, AppointmentTypeLink


def get_easter_monday(easter_sunday):
    return next_weekday(easter_sunday, 0)


def get_ascension_day(easter_sunday):
    return easter_sunday + datetime.timedelta(days=39)


class Command(BaseCommand):
    help = 'import holidays for the specified years'

    def add_arguments(self, parser):
        parser.add_argument('year', nargs='+', type=int)

    def handle(self, *args, **options):
        for location in Location.objects.exclude(name="Flying Team").all():
            for year in options['year']:
                self.stdout.write("importing holidays for year {} and location {}".format(year, location))
                # new years day
                self.create_holiday(year, 1, 1, "New Years Day", location)
                # easter monday
                easter_sunday = get_easter_sunday_date(year)
                easter_monday = get_easter_monday(easter_sunday)
                self.create_holiday(year, easter_monday.month, easter_monday.day, "Easter Monday", location)
                # ascension day
                ascension_day = get_ascension_day(easter_sunday)
                self.create_holiday(year, ascension_day.month, ascension_day.day, "Ascension Day", location)
                # pentecost monday
                pentecost_day = get_pentecost_day(easter_sunday)
                self.create_holiday(year, pentecost_day.month, pentecost_day.day, "Pentecost Monday", location)
                # labour day
                self.create_holiday(year, 5, 1, "Labour Day", location)
                # national day
                self.create_holiday(year, 6, 23, "National Day", location)
                # assumption day
                self.create_holiday(year, 8, 15, "Assumption Day", location)
                # all saints day
                self.create_holiday(year, 11, 1, "All Saints Day", location)
                # christmas
                self.create_holiday(year, 12, 25, "Christmas Day", location)
                self.create_holiday(year, 12, 26, "St Stephens Day", location)

    def create_holiday(self, year, month, day, comment, location):
        # check if already exists:
        count = Appointment.objects.filter(datetime_when__year=year, datetime_when__month=month, datetime_when__day=day,
                                           location=location, comment=comment).count()
        if count != 0:
            self.stdout.write(
                'an holiday with the same description already exists for the same day: {}'.format(comment))
            return
        holiday = Appointment()
        holiday.datetime_when = datetime.datetime(year=year, month=month, day=day, hour=9)
        holiday.location = location
        holiday.length = 60 * 8
        holiday.comment = comment
        holiday.visit_id = None
        holiday.save()
        appointment_type_other, _ = AppointmentType.objects.get_or_create(code='OTHER', defaults={'default_duration': 60})
        link = AppointmentTypeLink(appointment=holiday, appointment_type=appointment_type_other)
        link.save()


def get_easter_sunday_date(year):
    # source: http://www.officeholidays.com/religious/christian/easter_monday.php
    c = year // 100
    n = year - 19 * (year // 19)
    k = (c - 17) // 25
    i = c - c // 4 - (c - k) // 3 + 19 * n + 15
    i = i - 30 * (i // 30)
    i = i - (i // 28) * (1 - (i // 28) * (29 // (i + 1)) * ((21 - n) // 11))
    j = year + year // 4 + i + 2 - c + c // 4
    j = j - 7 * (j // 7)
    l = i - j
    month = 3 + (l + 40) // 44
    day = l + 28 - 31 * (month // 4)
    return datetime.datetime(year=year, month=month, day=day)


def get_pentecost_day(easter_sunday):
    return easter_sunday + datetime.timedelta(days=50)


def next_weekday(day_datetime, week_day):
    days_ahead = week_day - day_datetime.weekday()
    if days_ahead <= 0:
        days_ahead += 7
    return day_datetime + datetime.timedelta(days_ahead)