]> AND Private Git Repository - predictops.git/blob - predictops/source/holidays.py
Logo AND Algorithmique Numérique Distribuée

Private GIT Repository
Reducing the computation time and adding holidays features
[predictops.git] / predictops / source / holidays.py
1 from configparser import ConfigParser
2 from datetime import datetime, timedelta
3 from jours_feries_france.compute import JoursFeries
4 from logging import getLogger
5 from logging.config import fileConfig
6 from vacances_scolaires_france import SchoolHolidayDates
7
8 import itertools
9
10 fileConfig((Path.cwd() / 'config') / 'logging.cfg')
11 logger = getLogger()
12
13 class Holidays:
14
15     _start = None
16     _end   = None
17
18     def __init__(self, config_file):
19
20         self._config = ConfigParser()
21         self._config.read(config_file)
22
23         # Collecting holidays features
24         self._features = [section for section in self._config
25                               if self._config[section].getboolean('numerical')
26                               or self._config[section].getboolean('categorical')]
27
28         self._dated_features = {}
29
30
31     @property
32     def start(self):
33         return self._start
34
35     @start.setter
36     def start(self, x):
37         self._start = x
38
39
40     @property
41     def end(self):
42         return self._end
43
44     @end.setter
45     def end(self, x):
46         self._end = x
47
48
49
50     def _get_academic_zone(self, name, date):
51         dict_zones = {
52         'Caen' : ('A', 'B'),
53         'Clermont-Ferrand' : ('A', 'A'),
54         'Grenoble' : ('A', 'A'),
55         'Lyon' : ('A', 'A'),
56         'Montpellier' : ('A', 'C'),
57         'Nancy-Metz' : ('A', 'B'),
58         'Nantes' : ('A', 'B'),
59         'Rennes' : ('A', 'B'),
60         'Toulouse' : ('A', 'C'),
61         'Aix-Marseille' : ('B', 'B'),
62         'Amiens' : ('B', 'B'),
63         'Besançon' : ('B', 'A'),
64         'Dijon' : ('B', 'A'),
65         'Lille' : ('B', 'B'),
66         'Limoges' : ('B', 'A'),
67         'Nice' : ('B', 'B'),
68         'Orléans-Tours' : ('B', 'B'),
69         'Poitiers' : ('B', 'A'),
70         'Reims' : ('B', 'B'),
71         'Rouen ' : ('B', 'B'),
72         'Strasbourg' : ('B', 'B'),
73         'Bordeaux' : ('C', 'A'),
74         'Créteil' : ('C', 'C'),
75         'Paris' : ('C', 'C'),
76         'Versailles' : ('C', 'C')
77         }
78         if date < datetime(2016, 1, 1):
79             return dict_zones[name][0]
80         else:
81             return dict_zones[name][1]
82
83
84     @property
85     def dated_features(self):
86         if self._dated_features == {}:
87             logger.info("Adding holidays features")
88             bankHolidays = tuple(itertools.chain.from_iterable(list(JoursFeries.for_year(k).values())
89                                            for k in range(self.start.year, self.end.year+1)))
90             bankHolidaysEve = tuple(u-timedelta(days=1) for u in bankHolidays)
91             name = self._config['ZONE']['name']
92             date = self._start
93             d = SchoolHolidayDates()
94             while date <= self._end:
95                 Date = datetime.date(date)
96                 tomorrow = date + timedelta(days=1)
97                 Tomorrow = datetime.date(tomorrow)
98                 dict_hour = {
99                     'bankHolidays' : Date in bankHolidays,
100                     'bankHolidaysEve': Date in bankHolidaysEve,
101                     'holidays': d.is_holiday_for_zone(Date, self._get_academic_zone(name, date)),
102                     'holidaysEve': d.is_holiday_for_zone(Tomorrow, self._get_academic_zone(name, tomorrow))
103                 }
104                 self._dated_features[date] = dict_hour
105                 date += timedelta(hours=1)
106         return self._dated_features