0001-add-school-holidays-connector-63013.patch
debian/control | ||
---|---|---|
37 | 37 |
python3-feedparser, |
38 | 38 |
python3-pdfrw, |
39 | 39 |
python3-httplib2, |
40 |
python3-vobject, |
|
40 | 41 |
python3-xmlschema |
41 | 42 |
Description: Uniform access to multiple data sources and services (Python module) |
42 | 43 |
passerelle/apps/holidays/forms.py | ||
---|---|---|
1 |
# passerelle - uniform access to multiple data sources and services |
|
2 |
# Copyright (C) 2022 Entr'ouvert |
|
3 |
# |
|
4 |
# This program is free software: you can redistribute it and/or modify it |
|
5 |
# under the terms of the GNU Affero General Public License as published |
|
6 |
# by the Free Software Foundation, either version 3 of the License, or |
|
7 |
# (at your option) any later version. |
|
8 |
# |
|
9 |
# This program is distributed in the hope that it will be useful, |
|
10 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 |
# GNU Affero General Public License for more details. |
|
13 |
# |
|
14 |
# You should have received a copy of the GNU Affero General Public License |
|
15 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 |
from django import forms |
|
17 |
from django.utils.translation import ugettext_lazy as _ |
|
18 | ||
19 |
from passerelle.forms import GenericConnectorForm |
|
20 | ||
21 | ||
22 |
class HolidaysConnectorForm(GenericConnectorForm): |
|
23 |
def __init__(self, *args, **kwargs): |
|
24 |
from .models import HOLIDAYS_CHOICES |
|
25 | ||
26 |
super().__init__(*args, **kwargs) |
|
27 |
self.fields['holidays'] = forms.MultipleChoiceField( |
|
28 |
choices=HOLIDAYS_CHOICES, |
|
29 |
widget=forms.CheckboxSelectMultiple, |
|
30 |
initial=[x[0] for x in HOLIDAYS_CHOICES], |
|
31 |
label=_('Holidays'), |
|
32 |
) |
passerelle/apps/holidays/migrations/0001_initial.py | ||
---|---|---|
1 |
# Generated by Django 2.2.19 on 2022-03-23 12:09 |
|
2 | ||
3 |
import django.contrib.postgres.fields |
|
4 |
from django.db import migrations, models |
|
5 | ||
6 | ||
7 |
class Migration(migrations.Migration): |
|
8 | ||
9 |
initial = True |
|
10 | ||
11 |
dependencies = [ |
|
12 |
('base', '0029_auto_20210202_1627'), |
|
13 |
] |
|
14 | ||
15 |
operations = [ |
|
16 |
migrations.CreateModel( |
|
17 |
name='Holidays', |
|
18 |
fields=[ |
|
19 |
( |
|
20 |
'id', |
|
21 |
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), |
|
22 |
), |
|
23 |
('title', models.CharField(max_length=50, verbose_name='Title')), |
|
24 |
('slug', models.SlugField(unique=True, verbose_name='Identifier')), |
|
25 |
('description', models.TextField(verbose_name='Description')), |
|
26 |
( |
|
27 |
'zone', |
|
28 |
models.CharField( |
|
29 |
choices=[('a', 'A'), ('b', 'B'), ('c', 'C')], max_length=16, verbose_name='Zone' |
|
30 |
), |
|
31 |
), |
|
32 |
( |
|
33 |
'holidays', |
|
34 |
django.contrib.postgres.fields.ArrayField( |
|
35 |
base_field=models.CharField( |
|
36 |
choices=[ |
|
37 |
('winter_holidays', 'Vacances d’Hiver'), |
|
38 |
('spring_holidays', 'Vacances de Pâques'), |
|
39 |
('summer_holidays', 'Vacances d’Été'), |
|
40 |
('all_saints_holidays', 'Vacances de la Toussaint'), |
|
41 |
('christmas_holidays', 'Vacances de Noël'), |
|
42 |
('fathers_day', 'Fête des Pères'), |
|
43 |
('mothers_day', 'Fête des Mères'), |
|
44 |
], |
|
45 |
max_length=32, |
|
46 |
), |
|
47 |
size=None, |
|
48 |
verbose_name='Holidays', |
|
49 |
), |
|
50 |
), |
|
51 |
( |
|
52 |
'users', |
|
53 |
models.ManyToManyField( |
|
54 |
blank=True, |
|
55 |
related_name='_holidays_users_+', |
|
56 |
related_query_name='+', |
|
57 |
to='base.ApiUser', |
|
58 |
), |
|
59 |
), |
|
60 |
], |
|
61 |
options={ |
|
62 |
'verbose_name': 'School holidays', |
|
63 |
}, |
|
64 |
), |
|
65 |
] |
passerelle/apps/holidays/models.py | ||
---|---|---|
1 |
# -*- coding: utf-8 -*- |
|
2 |
# Copyright (C) 2022 Entr'ouvert |
|
3 |
# |
|
4 |
# This program is free software: you can redistribute it and/or modify it |
|
5 |
# under the terms of the GNU Affero General Public License as published |
|
6 |
# by the Free Software Foundation, either version 3 of the License, or |
|
7 |
# (at your option) any later version. |
|
8 |
# |
|
9 |
# This program is distributed in the hope that it will be useful, |
|
10 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 |
# GNU Affero General Public License for more details. |
|
13 |
# |
|
14 |
# You should have received a copy of the GNU Affero General Public License |
|
15 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
16 | ||
17 |
import requests |
|
18 |
import vobject |
|
19 |
from django.contrib.postgres.fields import ArrayField |
|
20 |
from django.db import models |
|
21 |
from django.http import HttpResponse |
|
22 |
from django.utils.translation import ugettext_lazy as _ |
|
23 | ||
24 |
from passerelle.base.models import BaseResource |
|
25 |
from passerelle.utils.api import endpoint |
|
26 |
from passerelle.utils.jsonresponse import APIError |
|
27 | ||
28 |
from .forms import HolidaysConnectorForm |
|
29 | ||
30 |
ZONE_CHOICES = ( |
|
31 |
('a', 'A'), |
|
32 |
('b', 'B'), |
|
33 |
('c', 'C'), |
|
34 |
) |
|
35 | ||
36 |
HOLIDAYS_LABELS = { |
|
37 |
'winter_holidays': "Vacances d’Hiver", |
|
38 |
'spring_holidays': 'Vacances de Pâques', |
|
39 |
'summer_holidays': "Vacances d’Été", |
|
40 |
'all_saints_holidays': 'Vacances de la Toussaint', |
|
41 |
'christmas_holidays': 'Vacances de Noël', |
|
42 |
} |
|
43 | ||
44 | ||
45 |
HOLIDAYS_CHOICES = [(x[0], x[1]) for x in HOLIDAYS_LABELS.items()] |
|
46 | ||
47 | ||
48 |
ZONE_URLS = { |
|
49 |
'a': 'https://fr.ftp.opendatasoft.com/openscol/fr-en-calendrier-scolaire/Zone-A.ics', |
|
50 |
'b': 'https://fr.ftp.opendatasoft.com/openscol/fr-en-calendrier-scolaire/Zone-B.ics', |
|
51 |
'c': 'https://fr.ftp.opendatasoft.com/openscol/fr-en-calendrier-scolaire/Zone-C.ics', |
|
52 |
} |
|
53 | ||
54 | ||
55 |
HOLIDAYS_MAPPING = { |
|
56 |
"Vacances d'Hiver": 'winter_holidays', |
|
57 |
'Vacances de Printemps': 'spring_holidays', |
|
58 |
"Vacances d'Été (Élèves)": 'summer_holidays', |
|
59 |
"Vacances d'Été": 'summer_holidays', |
|
60 |
'Vacances de la Toussaint': 'all_saints_holidays', |
|
61 |
'Vacances de Noël': 'christmas_holidays', |
|
62 |
} |
|
63 | ||
64 | ||
65 |
class Holidays(BaseResource): |
|
66 |
zone = models.CharField(_('Zone'), max_length=16, choices=ZONE_CHOICES) |
|
67 |
holidays = ArrayField( |
|
68 |
models.CharField(max_length=32, choices=HOLIDAYS_CHOICES), |
|
69 |
verbose_name=_('Holidays'), |
|
70 |
blank=False, |
|
71 |
null=False, |
|
72 |
) |
|
73 | ||
74 |
category = _('Misc') |
|
75 |
manager_form_base_class = HolidaysConnectorForm |
|
76 | ||
77 |
class Meta: |
|
78 |
verbose_name = _('School holidays') |
|
79 | ||
80 |
def get_holidays_display(self): |
|
81 |
return ', '.join(HOLIDAYS_LABELS[holiday] for holiday in self.holidays) |
|
82 | ||
83 |
@endpoint(name='holidays.ics', description=_('Get holidays ICS.')) |
|
84 |
def holidays_ics(self, request): |
|
85 |
try: |
|
86 |
response = requests.get(ZONE_URLS[self.zone]) |
|
87 |
response.raise_for_status() |
|
88 |
except requests.exceptions.RequestException as e: |
|
89 |
raise APIError('Error while getting ICS file: %s' % e) |
|
90 | ||
91 |
try: |
|
92 |
parsed = vobject.readOne(response.text) |
|
93 |
except vobject.base.ParseError as e: |
|
94 |
raise APIError('Invalid ICS file: %s' % e) |
|
95 | ||
96 |
if not parsed.contents.get('vevent'): |
|
97 |
raise APIError('ICS file does not contain events.') |
|
98 | ||
99 |
cal = vobject.iCalendar() |
|
100 |
for vevent in parsed.contents.get('vevent'): |
|
101 |
description = vevent.contents['description'][0].value |
|
102 | ||
103 |
holiday_id = HOLIDAYS_MAPPING.get(description) |
|
104 |
if holiday_id not in self.holidays: |
|
105 |
continue |
|
106 | ||
107 |
new_vevent = cal.add('vevent') |
|
108 |
new_vevent.add('summary').value = HOLIDAYS_LABELS[holiday_id] |
|
109 |
new_vevent.add('uid').value = '%s-%s' % (holiday_id, vevent.dtstart.value.year) |
|
110 |
new_vevent.add('categories').value = [holiday_id] |
|
111 |
new_vevent.add('dtstart').value = vevent.dtstart.value |
|
112 |
new_vevent.add('dtend').value = vevent.dtend.value |
|
113 | ||
114 |
return HttpResponse(cal.serialize(), content_type='text/calendar') |
passerelle/settings.py | ||
---|---|---|
146 | 146 |
'passerelle.apps.franceconnect_data', |
147 | 147 |
'passerelle.apps.gdc', |
148 | 148 |
'passerelle.apps.gesbac', |
149 |
'passerelle.apps.holidays', |
|
149 | 150 |
'passerelle.apps.jsondatastore', |
150 | 151 |
'passerelle.apps.maelis', |
151 | 152 |
'passerelle.apps.mdel', |
passerelle/urls.py | ||
---|---|---|
125 | 125 |
r'^(?P<connector>[\w,-]+)/(?P<slug>[\w,-]+)/$', GenericConnectorView.as_view(), name='view-connector' |
126 | 126 |
), |
127 | 127 |
url( |
128 |
r'^(?P<connector>[\w,-]+)/(?P<slug>[\w,-]+)/(?P<endpoint>[\w,-]+)(?:/(?P<rest>.*))?$', |
|
128 |
r'^(?P<connector>[\w,-]+)/(?P<slug>[\w,-]+)/(?P<endpoint>[\w,-.]+)(?:/(?P<rest>.*))?$',
|
|
129 | 129 |
GenericEndpointView.as_view(), |
130 | 130 |
name='generic-endpoint', |
131 | 131 |
), |
setup.py | ||
---|---|---|
125 | 125 |
'httplib2', |
126 | 126 |
'xmlschema', |
127 | 127 |
'pytz', |
128 |
'vobject', |
|
128 | 129 |
], |
129 | 130 |
cmdclass={ |
130 | 131 |
'build': build, |
tests/data/holidays/Zone-A.ics | ||
---|---|---|
1 |
BEGIN:VCALENDAR |
|
2 |
PRODID:-//MENJS//Calendrier//FR |
|
3 |
VERSION:2.0 |
|
4 |
CALSCALE:GREGORIAN |
|
5 |
X-WR-CALNAME:Calendrier scolaire - Zone A |
|
6 |
X-WR-TIMEZONE:Europe/Paris |
|
7 |
X-WR-CALDESC:Congés scolaires de la zone A depuis l'année 2017-2018 |
|
8 |
BEGIN:VTIMEZONE |
|
9 |
TZID:Europe/Paris |
|
10 |
X-LIC-LOCATION:Europe/Paris |
|
11 |
BEGIN:DAYLIGHT |
|
12 |
DTSTART:19700329T020000 |
|
13 |
TZNAME:CEST |
|
14 |
TZOFFSETFROM:+0100 |
|
15 |
TZOFFSETTO:+0200 |
|
16 |
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=3;BYDAY=-1SU |
|
17 |
TZNAME:CET |
|
18 |
END:DAYLIGHT |
|
19 |
BEGIN:STANDARD |
|
20 |
DTSTART:19701025T030000 |
|
21 |
TZOFFSETFROM:+0200 |
|
22 |
TZOFFSETTO:+0100 |
|
23 |
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=10;BYDAY=-1SU |
|
24 |
END:STANDARD |
|
25 |
END:VTIMEZONE |
|
26 |
BEGIN:VEVENT |
|
27 |
DTSTAMP:20220301T030012Z |
|
28 |
DTSTART;VALUE=DATE:20171021 |
|
29 |
DTEND;VALUE=DATE:20171106 |
|
30 |
SUMMARY:Vacances de la Toussaint |
|
31 |
UID:20220301T030012Z-Zone-A@data.education.gouv.fr |
|
32 |
LOCATION: |
|
33 |
DESCRIPTION:Vacances de la Toussaint |
|
34 |
TRANSP:TRANSPARENT |
|
35 |
END:VEVENT |
|
36 |
BEGIN:VEVENT |
|
37 |
DTSTAMP:20220301T030012Z |
|
38 |
DTSTART;VALUE=DATE:20171223 |
|
39 |
DTEND;VALUE=DATE:20180108 |
|
40 |
SUMMARY:Vacances de Noël |
|
41 |
UID:20220301T030013Z-Zone-A@data.education.gouv.fr |
|
42 |
LOCATION: |
|
43 |
DESCRIPTION:Vacances de Noël |
|
44 |
TRANSP:TRANSPARENT |
|
45 |
END:VEVENT |
|
46 |
BEGIN:VEVENT |
|
47 |
DTSTAMP:20220301T030012Z |
|
48 |
DTSTART;VALUE=DATE:20180210 |
|
49 |
DTEND;VALUE=DATE:20180226 |
|
50 |
SUMMARY:Vacances d'Hiver |
|
51 |
UID:20220301T030014Z-Zone-A@data.education.gouv.fr |
|
52 |
LOCATION: |
|
53 |
DESCRIPTION:Vacances d'Hiver |
|
54 |
TRANSP:TRANSPARENT |
|
55 |
END:VEVENT |
|
56 |
BEGIN:VEVENT |
|
57 |
DTSTAMP:20220301T030012Z |
|
58 |
DTSTART;VALUE=DATE:20180407 |
|
59 |
DTEND;VALUE=DATE:20180423 |
|
60 |
SUMMARY:Vacances de Printemps |
|
61 |
UID:20220301T030015Z-Zone-A@data.education.gouv.fr |
|
62 |
LOCATION: |
|
63 |
DESCRIPTION:Vacances de Printemps |
|
64 |
TRANSP:TRANSPARENT |
|
65 |
END:VEVENT |
|
66 |
BEGIN:VEVENT |
|
67 |
DTSTAMP:20220301T030012Z |
|
68 |
DTSTART;VALUE=DATE:20180707 |
|
69 |
DTEND;VALUE=DATE:20180831 |
|
70 |
SUMMARY:Vacances d'Été |
|
71 |
UID:20220301T030016Z-Zone-A@data.education.gouv.fr |
|
72 |
LOCATION: |
|
73 |
DESCRIPTION:Vacances d'Été (Enseignants) |
|
74 |
TRANSP:TRANSPARENT |
|
75 |
END:VEVENT |
|
76 |
BEGIN:VEVENT |
|
77 |
DTSTAMP:20220301T030012Z |
|
78 |
DTSTART;VALUE=DATE:20180707 |
|
79 |
DTEND;VALUE=DATE:20180903 |
|
80 |
SUMMARY:Vacances d'Été |
|
81 |
UID:20220301T030017Z-Zone-A@data.education.gouv.fr |
|
82 |
LOCATION: |
|
83 |
DESCRIPTION:Vacances d'Été (Élèves) |
|
84 |
TRANSP:TRANSPARENT |
|
85 |
END:VEVENT |
|
86 |
BEGIN:VEVENT |
|
87 |
DTSTAMP:20220301T030012Z |
|
88 |
DTSTART;VALUE=DATE:20181020 |
|
89 |
DTEND;VALUE=DATE:20181105 |
|
90 |
SUMMARY:Vacances de la Toussaint |
|
91 |
UID:20220301T030018Z-Zone-A@data.education.gouv.fr |
|
92 |
LOCATION: |
|
93 |
DESCRIPTION:Vacances de la Toussaint |
|
94 |
TRANSP:TRANSPARENT |
|
95 |
END:VEVENT |
|
96 |
BEGIN:VEVENT |
|
97 |
DTSTAMP:20220301T030012Z |
|
98 |
DTSTART;VALUE=DATE:20181222 |
|
99 |
DTEND;VALUE=DATE:20190107 |
|
100 |
SUMMARY:Vacances de Noël |
|
101 |
UID:20220301T030019Z-Zone-A@data.education.gouv.fr |
|
102 |
LOCATION: |
|
103 |
DESCRIPTION:Vacances de Noël |
|
104 |
TRANSP:TRANSPARENT |
|
105 |
END:VEVENT |
|
106 |
BEGIN:VEVENT |
|
107 |
DTSTAMP:20220301T030012Z |
|
108 |
DTSTART;VALUE=DATE:20190216 |
|
109 |
DTEND;VALUE=DATE:20190304 |
|
110 |
SUMMARY:Vacances d'Hiver |
|
111 |
UID:20220301T030020Z-Zone-A@data.education.gouv.fr |
|
112 |
LOCATION: |
|
113 |
DESCRIPTION:Vacances d'Hiver |
|
114 |
TRANSP:TRANSPARENT |
|
115 |
END:VEVENT |
|
116 |
BEGIN:VEVENT |
|
117 |
DTSTAMP:20220301T030012Z |
|
118 |
DTSTART;VALUE=DATE:20190413 |
|
119 |
DTEND;VALUE=DATE:20190429 |
|
120 |
SUMMARY:Vacances de Printemps |
|
121 |
UID:20220301T030021Z-Zone-A@data.education.gouv.fr |
|
122 |
LOCATION: |
|
123 |
DESCRIPTION:Vacances de Printemps |
|
124 |
TRANSP:TRANSPARENT |
|
125 |
END:VEVENT |
|
126 |
BEGIN:VEVENT |
|
127 |
DTSTAMP:20220301T030012Z |
|
128 |
DTSTART;VALUE=DATE:20190529 |
|
129 |
DTEND;VALUE=DATE:20190603 |
|
130 |
SUMMARY:Pont de l'Ascension |
|
131 |
UID:20220301T030022Z-Zone-A@data.education.gouv.fr |
|
132 |
LOCATION: |
|
133 |
DESCRIPTION:Pont de l'Ascension |
|
134 |
TRANSP:TRANSPARENT |
|
135 |
END:VEVENT |
|
136 |
BEGIN:VEVENT |
|
137 |
DTSTAMP:20220301T030012Z |
|
138 |
DTSTART;VALUE=DATE:20190706 |
|
139 |
DTEND;VALUE=DATE:20190830 |
|
140 |
SUMMARY:Vacances d'Été |
|
141 |
UID:20220301T030023Z-Zone-A@data.education.gouv.fr |
|
142 |
LOCATION: |
|
143 |
DESCRIPTION:Vacances d'Été (Enseignants) |
|
144 |
TRANSP:TRANSPARENT |
|
145 |
END:VEVENT |
|
146 |
BEGIN:VEVENT |
|
147 |
DTSTAMP:20220301T030012Z |
|
148 |
DTSTART;VALUE=DATE:20190706 |
|
149 |
DTEND;VALUE=DATE:20190902 |
|
150 |
SUMMARY:Vacances d'Été |
|
151 |
UID:20220301T030024Z-Zone-A@data.education.gouv.fr |
|
152 |
LOCATION: |
|
153 |
DESCRIPTION:Vacances d'Été (Élèves) |
|
154 |
TRANSP:TRANSPARENT |
|
155 |
END:VEVENT |
|
156 |
BEGIN:VEVENT |
|
157 |
DTSTAMP:20220301T030012Z |
|
158 |
DTSTART;VALUE=DATE:20191019 |
|
159 |
DTEND;VALUE=DATE:20191104 |
|
160 |
SUMMARY:Vacances de la Toussaint |
|
161 |
UID:20220301T030025Z-Zone-A@data.education.gouv.fr |
|
162 |
LOCATION: |
|
163 |
DESCRIPTION:Vacances de la Toussaint |
|
164 |
TRANSP:TRANSPARENT |
|
165 |
END:VEVENT |
|
166 |
BEGIN:VEVENT |
|
167 |
DTSTAMP:20220301T030012Z |
|
168 |
DTSTART;VALUE=DATE:20191221 |
|
169 |
DTEND;VALUE=DATE:20200106 |
|
170 |
SUMMARY:Vacances de Noël |
|
171 |
UID:20220301T030026Z-Zone-A@data.education.gouv.fr |
|
172 |
LOCATION: |
|
173 |
DESCRIPTION:Vacances de Noël |
|
174 |
TRANSP:TRANSPARENT |
|
175 |
END:VEVENT |
|
176 |
BEGIN:VEVENT |
|
177 |
DTSTAMP:20220301T030012Z |
|
178 |
DTSTART;VALUE=DATE:20200222 |
|
179 |
DTEND;VALUE=DATE:20200309 |
|
180 |
SUMMARY:Vacances d'Hiver |
|
181 |
UID:20220301T030027Z-Zone-A@data.education.gouv.fr |
|
182 |
LOCATION: |
|
183 |
DESCRIPTION:Vacances d'Hiver |
|
184 |
TRANSP:TRANSPARENT |
|
185 |
END:VEVENT |
|
186 |
BEGIN:VEVENT |
|
187 |
DTSTAMP:20220301T030012Z |
|
188 |
DTSTART;VALUE=DATE:20200418 |
|
189 |
DTEND;VALUE=DATE:20200504 |
|
190 |
SUMMARY:Vacances de Printemps |
|
191 |
UID:20220301T030028Z-Zone-A@data.education.gouv.fr |
|
192 |
LOCATION: |
|
193 |
DESCRIPTION:Vacances de Printemps |
|
194 |
TRANSP:TRANSPARENT |
|
195 |
END:VEVENT |
|
196 |
BEGIN:VEVENT |
|
197 |
DTSTAMP:20220301T030012Z |
|
198 |
DTSTART;VALUE=DATE:20200520 |
|
199 |
DTEND;VALUE=DATE:20200525 |
|
200 |
SUMMARY:Pont de l'Ascension |
|
201 |
UID:20220301T030029Z-Zone-A@data.education.gouv.fr |
|
202 |
LOCATION: |
|
203 |
DESCRIPTION:Pont de l'Ascension |
|
204 |
TRANSP:TRANSPARENT |
|
205 |
END:VEVENT |
|
206 |
BEGIN:VEVENT |
|
207 |
DTSTAMP:20220301T030012Z |
|
208 |
DTSTART;VALUE=DATE:20200704 |
|
209 |
DTEND;VALUE=DATE:20200901 |
|
210 |
SUMMARY:Vacances d'Été |
|
211 |
UID:20220301T030030Z-Zone-A@data.education.gouv.fr |
|
212 |
LOCATION: |
|
213 |
DESCRIPTION:Vacances d'Été |
|
214 |
TRANSP:TRANSPARENT |
|
215 |
END:VEVENT |
|
216 |
BEGIN:VEVENT |
|
217 |
DTSTAMP:20220301T030012Z |
|
218 |
DTSTART;VALUE=DATE:20201017 |
|
219 |
DTEND;VALUE=DATE:20201102 |
|
220 |
SUMMARY:Vacances de la Toussaint |
|
221 |
UID:20220301T030031Z-Zone-A@data.education.gouv.fr |
|
222 |
LOCATION: |
|
223 |
DESCRIPTION:Vacances de la Toussaint |
|
224 |
TRANSP:TRANSPARENT |
|
225 |
END:VEVENT |
|
226 |
BEGIN:VEVENT |
|
227 |
DTSTAMP:20220301T030012Z |
|
228 |
DTSTART;VALUE=DATE:20201219 |
|
229 |
DTEND;VALUE=DATE:20210104 |
|
230 |
SUMMARY:Vacances de Noël |
|
231 |
UID:20220301T030032Z-Zone-A@data.education.gouv.fr |
|
232 |
LOCATION: |
|
233 |
DESCRIPTION:Vacances de Noël |
|
234 |
TRANSP:TRANSPARENT |
|
235 |
END:VEVENT |
|
236 |
BEGIN:VEVENT |
|
237 |
DTSTAMP:20220301T030012Z |
|
238 |
DTSTART;VALUE=DATE:20210206 |
|
239 |
DTEND;VALUE=DATE:20210222 |
|
240 |
SUMMARY:Vacances d'Hiver |
|
241 |
UID:20220301T030033Z-Zone-A@data.education.gouv.fr |
|
242 |
LOCATION: |
|
243 |
DESCRIPTION:Vacances d'Hiver |
|
244 |
TRANSP:TRANSPARENT |
|
245 |
END:VEVENT |
|
246 |
BEGIN:VEVENT |
|
247 |
DTSTAMP:20220301T030012Z |
|
248 |
DTSTART;VALUE=DATE:20210410 |
|
249 |
DTEND;VALUE=DATE:20210426 |
|
250 |
SUMMARY:Vacances de Printemps |
|
251 |
UID:20220301T030034Z-Zone-A@data.education.gouv.fr |
|
252 |
LOCATION: |
|
253 |
DESCRIPTION:Vacances de Printemps |
|
254 |
TRANSP:TRANSPARENT |
|
255 |
END:VEVENT |
|
256 |
BEGIN:VEVENT |
|
257 |
DTSTAMP:20220301T030012Z |
|
258 |
DTSTART;VALUE=DATE:20210513 |
|
259 |
DTEND;VALUE=DATE:20210517 |
|
260 |
SUMMARY:Pont de l'Ascension |
|
261 |
UID:20220301T030035Z-Zone-A@data.education.gouv.fr |
|
262 |
LOCATION: |
|
263 |
DESCRIPTION:Pont de l'Ascension |
|
264 |
TRANSP:TRANSPARENT |
|
265 |
END:VEVENT |
|
266 |
BEGIN:VEVENT |
|
267 |
DTSTAMP:20220301T030012Z |
|
268 |
DTSTART;VALUE=DATE:20210706 |
|
269 |
DTEND;VALUE=DATE:20210901 |
|
270 |
SUMMARY:Vacances d'Été |
|
271 |
UID:20220301T030036Z-Zone-A@data.education.gouv.fr |
|
272 |
LOCATION: |
|
273 |
DESCRIPTION:Vacances d'Été (Enseignants) |
|
274 |
TRANSP:TRANSPARENT |
|
275 |
END:VEVENT |
|
276 |
BEGIN:VEVENT |
|
277 |
DTSTAMP:20220301T030012Z |
|
278 |
DTSTART;VALUE=DATE:20210706 |
|
279 |
DTEND;VALUE=DATE:20210902 |
|
280 |
SUMMARY:Vacances d'Été |
|
281 |
UID:20220301T030037Z-Zone-A@data.education.gouv.fr |
|
282 |
LOCATION: |
|
283 |
DESCRIPTION:Vacances d'Été (Élèves) |
|
284 |
TRANSP:TRANSPARENT |
|
285 |
END:VEVENT |
|
286 |
BEGIN:VEVENT |
|
287 |
DTSTAMP:20220301T030012Z |
|
288 |
DTSTART;VALUE=DATE:20211023 |
|
289 |
DTEND;VALUE=DATE:20211108 |
|
290 |
SUMMARY:Vacances de la Toussaint |
|
291 |
UID:20220301T030038Z-Zone-A@data.education.gouv.fr |
|
292 |
LOCATION: |
|
293 |
DESCRIPTION:Vacances de la Toussaint |
|
294 |
TRANSP:TRANSPARENT |
|
295 |
END:VEVENT |
|
296 |
BEGIN:VEVENT |
|
297 |
DTSTAMP:20220301T030012Z |
|
298 |
DTSTART;VALUE=DATE:20211218 |
|
299 |
DTEND;VALUE=DATE:20220103 |
|
300 |
SUMMARY:Vacances de Noël |
|
301 |
UID:20220301T030039Z-Zone-A@data.education.gouv.fr |
|
302 |
LOCATION: |
|
303 |
DESCRIPTION:Vacances de Noël |
|
304 |
TRANSP:TRANSPARENT |
|
305 |
END:VEVENT |
|
306 |
BEGIN:VEVENT |
|
307 |
DTSTAMP:20220301T030012Z |
|
308 |
DTSTART;VALUE=DATE:20220212 |
|
309 |
DTEND;VALUE=DATE:20220228 |
|
310 |
SUMMARY:Vacances d'Hiver |
|
311 |
UID:20220301T030040Z-Zone-A@data.education.gouv.fr |
|
312 |
LOCATION: |
|
313 |
DESCRIPTION:Vacances d'Hiver |
|
314 |
TRANSP:TRANSPARENT |
|
315 |
END:VEVENT |
|
316 |
BEGIN:VEVENT |
|
317 |
DTSTAMP:20220301T030012Z |
|
318 |
DTSTART;VALUE=DATE:20220416 |
|
319 |
DTEND;VALUE=DATE:20220502 |
|
320 |
SUMMARY:Vacances de Printemps |
|
321 |
UID:20220301T030041Z-Zone-A@data.education.gouv.fr |
|
322 |
LOCATION: |
|
323 |
DESCRIPTION:Vacances de Printemps |
|
324 |
TRANSP:TRANSPARENT |
|
325 |
END:VEVENT |
|
326 |
BEGIN:VEVENT |
|
327 |
DTSTAMP:20220301T030012Z |
|
328 |
DTSTART;VALUE=DATE:20220526 |
|
329 |
DTEND;VALUE=DATE:20220528 |
|
330 |
SUMMARY:Pont de l'Ascension |
|
331 |
UID:20220301T030042Z-Zone-A@data.education.gouv.fr |
|
332 |
LOCATION: |
|
333 |
DESCRIPTION:Pont de l'Ascension |
|
334 |
TRANSP:TRANSPARENT |
|
335 |
END:VEVENT |
|
336 |
BEGIN:VEVENT |
|
337 |
DTSTAMP:20220301T030012Z |
|
338 |
DTSTART;VALUE=DATE:20220707 |
|
339 |
DTEND;VALUE=DATE:20220831 |
|
340 |
SUMMARY:Vacances d'Été |
|
341 |
UID:20220301T030043Z-Zone-A@data.education.gouv.fr |
|
342 |
LOCATION: |
|
343 |
DESCRIPTION:Vacances d'Été (Enseignants) |
|
344 |
TRANSP:TRANSPARENT |
|
345 |
END:VEVENT |
|
346 |
BEGIN:VEVENT |
|
347 |
DTSTAMP:20220301T030012Z |
|
348 |
DTSTART;VALUE=DATE:20220707 |
|
349 |
DTEND;VALUE=DATE:20220901 |
|
350 |
SUMMARY:Vacances d'Été |
|
351 |
UID:20220301T030044Z-Zone-A@data.education.gouv.fr |
|
352 |
LOCATION: |
|
353 |
DESCRIPTION:Vacances d'Été (Élèves) |
|
354 |
TRANSP:TRANSPARENT |
|
355 |
END:VEVENT |
|
356 |
BEGIN:VEVENT |
|
357 |
DTSTAMP:20220301T030012Z |
|
358 |
DTSTART;VALUE=DATE:20221022 |
|
359 |
DTEND;VALUE=DATE:20221107 |
|
360 |
SUMMARY:Vacances de la Toussaint |
|
361 |
UID:20220301T030045Z-Zone-A@data.education.gouv.fr |
|
362 |
LOCATION: |
|
363 |
DESCRIPTION:Vacances de la Toussaint |
|
364 |
TRANSP:TRANSPARENT |
|
365 |
END:VEVENT |
|
366 |
BEGIN:VEVENT |
|
367 |
DTSTAMP:20220301T030012Z |
|
368 |
DTSTART;VALUE=DATE:20221217 |
|
369 |
DTEND;VALUE=DATE:20230103 |
|
370 |
SUMMARY:Vacances de Noël |
|
371 |
UID:20220301T030046Z-Zone-A@data.education.gouv.fr |
|
372 |
LOCATION: |
|
373 |
DESCRIPTION:Vacances de Noël |
|
374 |
TRANSP:TRANSPARENT |
|
375 |
END:VEVENT |
|
376 |
BEGIN:VEVENT |
|
377 |
DTSTAMP:20220301T030012Z |
|
378 |
DTSTART;VALUE=DATE:20230204 |
|
379 |
DTEND;VALUE=DATE:20230220 |
|
380 |
SUMMARY:Vacances d'Hiver |
|
381 |
UID:20220301T030047Z-Zone-A@data.education.gouv.fr |
|
382 |
LOCATION: |
|
383 |
DESCRIPTION:Vacances d'Hiver |
|
384 |
TRANSP:TRANSPARENT |
|
385 |
END:VEVENT |
|
386 |
BEGIN:VEVENT |
|
387 |
DTSTAMP:20220301T030012Z |
|
388 |
DTSTART;VALUE=DATE:20230408 |
|
389 |
DTEND;VALUE=DATE:20230424 |
|
390 |
SUMMARY:Vacances de Printemps |
|
391 |
UID:20220301T030048Z-Zone-A@data.education.gouv.fr |
|
392 |
LOCATION: |
|
393 |
DESCRIPTION:Vacances de Printemps |
|
394 |
TRANSP:TRANSPARENT |
|
395 |
END:VEVENT |
|
396 |
BEGIN:VEVENT |
|
397 |
DTSTAMP:20220301T030012Z |
|
398 |
DTSTART;VALUE=DATE:20230518 |
|
399 |
DTEND;VALUE=DATE:20230522 |
|
400 |
SUMMARY:Pont de l'Ascension |
|
401 |
UID:20220301T030049Z-Zone-A@data.education.gouv.fr |
|
402 |
LOCATION: |
|
403 |
DESCRIPTION:Pont de l'Ascension |
|
404 |
TRANSP:TRANSPARENT |
|
405 |
END:VEVENT |
|
406 |
BEGIN:VEVENT |
|
407 |
DTSTAMP:20220301T030012Z |
|
408 |
DTSTART;VALUE=DATE:20230708 |
|
409 |
DTEND;VALUE=DATE:20230708 |
|
410 |
SUMMARY:Début des Vacances d'Été |
|
411 |
UID:20220301T030050Z-Zone-A@data.education.gouv.fr |
|
412 |
LOCATION: |
|
413 |
DESCRIPTION:Début des Vacances d'Été |
|
414 |
TRANSP:TRANSPARENT |
|
415 |
END:VEVENT |
|
416 |
END:VCALENDAR |
tests/data/holidays/Zone-B.ics | ||
---|---|---|
1 |
BEGIN:VCALENDAR |
|
2 |
PRODID:-//MENJS//Calendrier//FR |
|
3 |
VERSION:2.0 |
|
4 |
CALSCALE:GREGORIAN |
|
5 |
X-WR-CALNAME:Calendrier scolaire - Zone B |
|
6 |
X-WR-TIMEZONE:Europe/Paris |
|
7 |
X-WR-CALDESC:Congés scolaires de la zone B depuis l'année 2017-2018 |
|
8 |
BEGIN:VTIMEZONE |
|
9 |
TZID:Europe/Paris |
|
10 |
X-LIC-LOCATION:Europe/Paris |
|
11 |
BEGIN:DAYLIGHT |
|
12 |
DTSTART:19700329T020000 |
|
13 |
TZNAME:CEST |
|
14 |
TZOFFSETFROM:+0100 |
|
15 |
TZOFFSETTO:+0200 |
|
16 |
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=3;BYDAY=-1SU |
|
17 |
TZNAME:CET |
|
18 |
END:DAYLIGHT |
|
19 |
BEGIN:STANDARD |
|
20 |
DTSTART:19701025T030000 |
|
21 |
TZOFFSETFROM:+0200 |
|
22 |
TZOFFSETTO:+0100 |
|
23 |
RRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=10;BYDAY=-1SU |
|
24 |
END:STANDARD |
|
25 |
END:VTIMEZONE |
|
26 |
BEGIN:VEVENT |
|
27 |
DTSTAMP:20220301T030012Z |
|
28 |
DTSTART;VALUE=DATE:20171021 |
|
29 |
DTEND;VALUE=DATE:20171106 |
|
30 |
SUMMARY:Vacances de la Toussaint |
|
31 |
UID:20220301T030051Z-Zone-B@data.education.gouv.fr |
|
32 |
LOCATION: |
|
33 |
DESCRIPTION:Vacances de la Toussaint |
|
34 |
TRANSP:TRANSPARENT |
|
35 |
END:VEVENT |
|
36 |
BEGIN:VEVENT |
|
37 |
DTSTAMP:20220301T030012Z |
|
38 |
DTSTART;VALUE=DATE:20171223 |
|
39 |
DTEND;VALUE=DATE:20180108 |
|
40 |
SUMMARY:Vacances de Noël |
|
41 |
UID:20220301T030052Z-Zone-B@data.education.gouv.fr |
|
42 |
LOCATION: |
|
43 |
DESCRIPTION:Vacances de Noël |
|
44 |
TRANSP:TRANSPARENT |
|
45 |
END:VEVENT |
|
46 |
BEGIN:VEVENT |
|
47 |
DTSTAMP:20220301T030012Z |
|
48 |
DTSTART;VALUE=DATE:20180224 |
|
49 |
DTEND;VALUE=DATE:20180312 |
|
50 |
SUMMARY:Vacances d'Hiver |
|
51 |
UID:20220301T030053Z-Zone-B@data.education.gouv.fr |
|
52 |
LOCATION: |
|
53 |
DESCRIPTION:Vacances d'Hiver |
|
54 |
TRANSP:TRANSPARENT |
|
55 |
END:VEVENT |
|
56 |
BEGIN:VEVENT |
|
57 |
DTSTAMP:20220301T030012Z |
|
58 |
DTSTART;VALUE=DATE:20180421 |
|
59 |
DTEND;VALUE=DATE:20180507 |
|
60 |
SUMMARY:Vacances de Printemps |
|
61 |
UID:20220301T030054Z-Zone-B@data.education.gouv.fr |
|
62 |
LOCATION: |
|
63 |
DESCRIPTION:Vacances de Printemps |
|
64 |
TRANSP:TRANSPARENT |
|
65 |
END:VEVENT |
|
66 |
BEGIN:VEVENT |
|
67 |
DTSTAMP:20220301T030012Z |
|
68 |
DTSTART;VALUE=DATE:20180707 |
|
69 |
DTEND;VALUE=DATE:20180831 |
|
70 |
SUMMARY:Vacances d'Été |
|
71 |
UID:20220301T030055Z-Zone-B@data.education.gouv.fr |
|
72 |
LOCATION: |
|
73 |
DESCRIPTION:Vacances d'Été (Enseignants) |
|
74 |
TRANSP:TRANSPARENT |
|
75 |
END:VEVENT |
|
76 |
BEGIN:VEVENT |
|
77 |
DTSTAMP:20220301T030012Z |
|
78 |
DTSTART;VALUE=DATE:20180707 |
|
79 |
DTEND;VALUE=DATE:20180903 |
|
80 |
SUMMARY:Vacances d'Été |
|
81 |
UID:20220301T030056Z-Zone-B@data.education.gouv.fr |
|
82 |
LOCATION: |
|
83 |
DESCRIPTION:Vacances d'Été (Élèves) |
|
84 |
TRANSP:TRANSPARENT |
|
85 |
END:VEVENT |
|
86 |
BEGIN:VEVENT |
|
87 |
DTSTAMP:20220301T030012Z |
|
88 |
DTSTART;VALUE=DATE:20181020 |
|
89 |
DTEND;VALUE=DATE:20181105 |
|
90 |
SUMMARY:Vacances de la Toussaint |
|
91 |
UID:20220301T030057Z-Zone-B@data.education.gouv.fr |
|
92 |
LOCATION: |
|
93 |
DESCRIPTION:Vacances de la Toussaint |
|
94 |
TRANSP:TRANSPARENT |
|
95 |
END:VEVENT |
|
96 |
BEGIN:VEVENT |
|
97 |
DTSTAMP:20220301T030012Z |
|
98 |
DTSTART;VALUE=DATE:20181222 |
|
99 |
DTEND;VALUE=DATE:20190107 |
|
100 |
SUMMARY:Vacances de Noël |
|
101 |
UID:20220301T030058Z-Zone-B@data.education.gouv.fr |
|
102 |
LOCATION: |
|
103 |
DESCRIPTION:Vacances de Noël |
|
104 |
TRANSP:TRANSPARENT |
|
105 |
END:VEVENT |
|
106 |
BEGIN:VEVENT |
|
107 |
DTSTAMP:20220301T030012Z |
|
108 |
DTSTART;VALUE=DATE:20190209 |
|
109 |
DTEND;VALUE=DATE:20190225 |
|
110 |
SUMMARY:Vacances d'Hiver |
|
111 |
UID:20220301T030059Z-Zone-B@data.education.gouv.fr |
|
112 |
LOCATION: |
|
113 |
DESCRIPTION:Vacances d'Hiver |
|
114 |
TRANSP:TRANSPARENT |
|
115 |
END:VEVENT |
|
116 |
BEGIN:VEVENT |
|
117 |
DTSTAMP:20220301T030012Z |
|
118 |
DTSTART;VALUE=DATE:20190406 |
|
119 |
DTEND;VALUE=DATE:20190423 |
|
120 |
SUMMARY:Vacances de Printemps |
|
121 |
UID:20220301T030100Z-Zone-B@data.education.gouv.fr |
|
122 |
LOCATION: |
|
123 |
DESCRIPTION:Vacances de Printemps |
|
124 |
TRANSP:TRANSPARENT |
|
125 |
END:VEVENT |
|
126 |
BEGIN:VEVENT |
|
127 |
DTSTAMP:20220301T030012Z |
|
128 |
DTSTART;VALUE=DATE:20190529 |
|
129 |
DTEND;VALUE=DATE:20190603 |
|
130 |
SUMMARY:Pont de l'Ascension |
|
131 |
UID:20220301T030101Z-Zone-B@data.education.gouv.fr |
|
132 |
LOCATION: |
|
133 |
DESCRIPTION:Pont de l'Ascension |
|
134 |
TRANSP:TRANSPARENT |
|
135 |
END:VEVENT |
|
136 |
BEGIN:VEVENT |
|
137 |
DTSTAMP:20220301T030012Z |
|
138 |
DTSTART;VALUE=DATE:20190706 |
|
139 |
DTEND;VALUE=DATE:20190830 |
|
140 |
SUMMARY:Vacances d'Été |
|
141 |
UID:20220301T030102Z-Zone-B@data.education.gouv.fr |
|
142 |
LOCATION: |
|
143 |
DESCRIPTION:Vacances d'Été (Enseignants) |
|
144 |
TRANSP:TRANSPARENT |
|
145 |
END:VEVENT |
|
146 |
BEGIN:VEVENT |
|
147 |
DTSTAMP:20220301T030012Z |
|
148 |
DTSTART;VALUE=DATE:20190706 |
|
149 |
DTEND;VALUE=DATE:20190902 |
|
150 |
SUMMARY:Vacances d'Été |
|
151 |
UID:20220301T030103Z-Zone-B@data.education.gouv.fr |
|
152 |
LOCATION: |
|
153 |
DESCRIPTION:Vacances d'Été (Élèves) |
|
154 |
TRANSP:TRANSPARENT |
|
155 |
END:VEVENT |
|
156 |
BEGIN:VEVENT |
|
157 |
DTSTAMP:20220301T030012Z |
|
158 |
DTSTART;VALUE=DATE:20191019 |
|
159 |
DTEND;VALUE=DATE:20191104 |
|
160 |
SUMMARY:Vacances de la Toussaint |
|
161 |
UID:20220301T030104Z-Zone-B@data.education.gouv.fr |
|
162 |
LOCATION: |
|
163 |
DESCRIPTION:Vacances de la Toussaint |
|
164 |
TRANSP:TRANSPARENT |
|
165 |
END:VEVENT |
|
166 |
BEGIN:VEVENT |
|
167 |
DTSTAMP:20220301T030012Z |
|
168 |
DTSTART;VALUE=DATE:20191221 |
|
169 |
DTEND;VALUE=DATE:20200106 |
|
170 |
SUMMARY:Vacances de Noël |
|
171 |
UID:20220301T030105Z-Zone-B@data.education.gouv.fr |
|
172 |
LOCATION: |
|
173 |
DESCRIPTION:Vacances de Noël |
|
174 |
TRANSP:TRANSPARENT |
|
175 |
END:VEVENT |
|
176 |
BEGIN:VEVENT |
|
177 |
DTSTAMP:20220301T030012Z |
|
178 |
DTSTART;VALUE=DATE:20200215 |
|
179 |
DTEND;VALUE=DATE:20200302 |
|
180 |
SUMMARY:Vacances d'Hiver |
|
181 |
UID:20220301T030106Z-Zone-B@data.education.gouv.fr |
|
182 |
LOCATION: |
|
183 |
DESCRIPTION:Vacances d'Hiver |
|
184 |
TRANSP:TRANSPARENT |
|
185 |
END:VEVENT |
|
186 |
BEGIN:VEVENT |
|
187 |
DTSTAMP:20220301T030012Z |
|
188 |
DTSTART;VALUE=DATE:20200411 |
|
189 |
DTEND;VALUE=DATE:20200427 |
|
190 |
SUMMARY:Vacances de Printemps |
|
191 |
UID:20220301T030107Z-Zone-B@data.education.gouv.fr |
|
192 |
LOCATION: |
|
193 |
DESCRIPTION:Vacances de Printemps |
|
194 |
TRANSP:TRANSPARENT |
|
195 |
END:VEVENT |
|
196 |
BEGIN:VEVENT |
|
197 |
DTSTAMP:20220301T030012Z |
|
198 |
DTSTART;VALUE=DATE:20200520 |
|
199 |
DTEND;VALUE=DATE:20200525 |
|
200 |
SUMMARY:Pont de l'Ascension |
|
201 |
UID:20220301T030108Z-Zone-B@data.education.gouv.fr |
|
202 |
LOCATION: |
|
203 |
DESCRIPTION:Pont de l'Ascension |
|
204 |
TRANSP:TRANSPARENT |
|
205 |
END:VEVENT |
|
206 |
BEGIN:VEVENT |
|
207 |
DTSTAMP:20220301T030012Z |
|
208 |
DTSTART;VALUE=DATE:20200704 |
|
209 |
DTEND;VALUE=DATE:20200901 |
|
210 |
SUMMARY:Vacances d'Été |
|
211 |
UID:20220301T030109Z-Zone-B@data.education.gouv.fr |
|
212 |
LOCATION: |
|
213 |
DESCRIPTION:Vacances d'Été |
|
214 |
TRANSP:TRANSPARENT |
|
215 |
END:VEVENT |
|
216 |
BEGIN:VEVENT |
|
217 |
DTSTAMP:20220301T030012Z |
|
218 |
DTSTART;VALUE=DATE:20201017 |
|
219 |
DTEND;VALUE=DATE:20201102 |
|
220 |
SUMMARY:Vacances de la Toussaint |
|
221 |
UID:20220301T030110Z-Zone-B@data.education.gouv.fr |
|
222 |
LOCATION: |
|
223 |
DESCRIPTION:Vacances de la Toussaint |
|
224 |
TRANSP:TRANSPARENT |
|
225 |
END:VEVENT |
|
226 |
BEGIN:VEVENT |
|
227 |
DTSTAMP:20220301T030012Z |
|
228 |
DTSTART;VALUE=DATE:20201219 |
|
229 |
DTEND;VALUE=DATE:20210104 |
|
230 |
SUMMARY:Vacances de Noël |
|
231 |
UID:20220301T030111Z-Zone-B@data.education.gouv.fr |
|
232 |
LOCATION: |
|
233 |
DESCRIPTION:Vacances de Noël |
|
234 |
TRANSP:TRANSPARENT |
|
235 |
END:VEVENT |
|
236 |
BEGIN:VEVENT |
|
237 |
DTSTAMP:20220301T030012Z |
|
238 |
DTSTART;VALUE=DATE:20210220 |
|
239 |
DTEND;VALUE=DATE:20210308 |
|
240 |
SUMMARY:Vacances d'Hiver |
|
241 |
UID:20220301T030112Z-Zone-B@data.education.gouv.fr |
|
242 |
LOCATION: |
|
243 |
DESCRIPTION:Vacances d'Hiver |
|
244 |
TRANSP:TRANSPARENT |
|
245 |
END:VEVENT |
|
246 |
BEGIN:VEVENT |
|
247 |
DTSTAMP:20220301T030012Z |
|
248 |
DTSTART;VALUE=DATE:20210410 |
|
249 |
DTEND;VALUE=DATE:20210426 |
|
250 |
SUMMARY:Vacances de Printemps |
|
251 |
UID:20220301T030113Z-Zone-B@data.education.gouv.fr |
|
252 |
LOCATION: |
|
253 |
DESCRIPTION:Vacances de Printemps |
|
254 |
TRANSP:TRANSPARENT |
|
255 |
END:VEVENT |
|
256 |
BEGIN:VEVENT |
|
257 |
DTSTAMP:20220301T030012Z |
|
258 |
DTSTART;VALUE=DATE:20210513 |
|
259 |
DTEND;VALUE=DATE:20210517 |
|
260 |
SUMMARY:Pont de l'Ascension |
|
261 |
UID:20220301T030114Z-Zone-B@data.education.gouv.fr |
|
262 |
LOCATION: |
|
263 |
DESCRIPTION:Pont de l'Ascension |
|
264 |
TRANSP:TRANSPARENT |
|
265 |
END:VEVENT |
|
266 |
BEGIN:VEVENT |
|
267 |
DTSTAMP:20220301T030012Z |
|
268 |
DTSTART;VALUE=DATE:20210706 |
|
269 |
DTEND;VALUE=DATE:20210901 |
|
270 |
SUMMARY:Vacances d'Été |
|
271 |
UID:20220301T030115Z-Zone-B@data.education.gouv.fr |
|
272 |
LOCATION: |
|
273 |
DESCRIPTION:Vacances d'Été (Enseignants) |
|
274 |
TRANSP:TRANSPARENT |
|
275 |
END:VEVENT |
|
276 |
BEGIN:VEVENT |
|
277 |
DTSTAMP:20220301T030012Z |
|
278 |
DTSTART;VALUE=DATE:20210706 |
|
279 |
DTEND;VALUE=DATE:20210902 |
|
280 |
SUMMARY:Vacances d'Été |
|
281 |
UID:20220301T030116Z-Zone-B@data.education.gouv.fr |
|
282 |
LOCATION: |
|
283 |
DESCRIPTION:Vacances d'Été (Élèves) |
|
284 |
TRANSP:TRANSPARENT |
|
285 |
END:VEVENT |
|
286 |
BEGIN:VEVENT |
|
287 |
DTSTAMP:20220301T030012Z |
|
288 |
DTSTART;VALUE=DATE:20211023 |
|
289 |
DTEND;VALUE=DATE:20211108 |
|
290 |
SUMMARY:Vacances de la Toussaint |
|
291 |
UID:20220301T030117Z-Zone-B@data.education.gouv.fr |
|
292 |
LOCATION: |
|
293 |
DESCRIPTION:Vacances de la Toussaint |
|
294 |
TRANSP:TRANSPARENT |
|
295 |
END:VEVENT |
|
296 |
BEGIN:VEVENT |
|
297 |
DTSTAMP:20220301T030012Z |
|
298 |
DTSTART;VALUE=DATE:20211218 |
|
299 |
DTEND;VALUE=DATE:20220103 |
|
300 |
SUMMARY:Vacances de Noël |
|
301 |
UID:20220301T030118Z-Zone-B@data.education.gouv.fr |
|
302 |
LOCATION: |
|
303 |
DESCRIPTION:Vacances de Noël |
|
304 |
TRANSP:TRANSPARENT |
|
305 |
END:VEVENT |
|
306 |
BEGIN:VEVENT |
|
307 |
DTSTAMP:20220301T030012Z |
|
308 |
DTSTART;VALUE=DATE:20220205 |
|
309 |
DTEND;VALUE=DATE:20220221 |
|
310 |
SUMMARY:Vacances d'Hiver |
|
311 |
UID:20220301T030119Z-Zone-B@data.education.gouv.fr |
|
312 |
LOCATION: |
|
313 |
DESCRIPTION:Vacances d'Hiver |
|
314 |
TRANSP:TRANSPARENT |
|
315 |
END:VEVENT |
|
316 |
BEGIN:VEVENT |
|
317 |
DTSTAMP:20220301T030012Z |
|
318 |
DTSTART;VALUE=DATE:20220409 |
|
319 |
DTEND;VALUE=DATE:20220425 |
|
320 |
SUMMARY:Vacances de Printemps |
|
321 |
UID:20220301T030120Z-Zone-B@data.education.gouv.fr |
|
322 |
LOCATION: |
|
323 |
DESCRIPTION:Vacances de Printemps |
|
324 |
TRANSP:TRANSPARENT |
|
325 |
END:VEVENT |
|
326 |
BEGIN:VEVENT |
|
327 |
DTSTAMP:20220301T030012Z |
|
328 |
DTSTART;VALUE=DATE:20220526 |
|
329 |
DTEND;VALUE=DATE:20220528 |
|
330 |
SUMMARY:Pont de l'Ascension |
|
331 |
UID:20220301T030121Z-Zone-B@data.education.gouv.fr |
|
332 |
LOCATION: |
|
333 |
DESCRIPTION:Pont de l'Ascension |
|
334 |
TRANSP:TRANSPARENT |
|
335 |
END:VEVENT |
|
336 |
BEGIN:VEVENT |
|
337 |
DTSTAMP:20220301T030012Z |
|
338 |
DTSTART;VALUE=DATE:20220707 |
|
339 |
DTEND;VALUE=DATE:20220831 |
|
340 |
SUMMARY:Vacances d'Été |
|
341 |
UID:20220301T030122Z-Zone-B@data.education.gouv.fr |
|
342 |
LOCATION: |
|
343 |
DESCRIPTION:Vacances d'Été (Enseignants) |
|
344 |
TRANSP:TRANSPARENT |
|
345 |
END:VEVENT |
|
346 |
BEGIN:VEVENT |
|
347 |
DTSTAMP:20220301T030012Z |
|
348 |
DTSTART;VALUE=DATE:20220707 |
|
349 |
DTEND;VALUE=DATE:20220901 |
|
350 |
SUMMARY:Vacances d'Été |
|
351 |
UID:20220301T030123Z-Zone-B@data.education.gouv.fr |
|
352 |
LOCATION: |
|
353 |
DESCRIPTION:Vacances d'Été (Élèves) |
|
354 |
TRANSP:TRANSPARENT |
|
355 |
END:VEVENT |
|
356 |
BEGIN:VEVENT |
|
357 |
DTSTAMP:20220301T030012Z |
|
358 |
DTSTART;VALUE=DATE:20221022 |
|
359 |
DTEND;VALUE=DATE:20221107 |
|
360 |
SUMMARY:Vacances de la Toussaint |
|
361 |
UID:20220301T030124Z-Zone-B@data.education.gouv.fr |
|
362 |
LOCATION: |
|
363 |
DESCRIPTION:Vacances de la Toussaint |
|
364 |
TRANSP:TRANSPARENT |
|
365 |
END:VEVENT |
|
366 |
BEGIN:VEVENT |
|
367 |
DTSTAMP:20220301T030012Z |
|
368 |
DTSTART;VALUE=DATE:20221217 |
|
369 |
DTEND;VALUE=DATE:20230103 |
|
370 |
SUMMARY:Vacances de Noël |
|
371 |
UID:20220301T030125Z-Zone-B@data.education.gouv.fr |
|
372 |
LOCATION: |
|
373 |
DESCRIPTION:Vacances de Noël |
|
374 |
TRANSP:TRANSPARENT |
|
375 |
END:VEVENT |
|
376 |
BEGIN:VEVENT |
|
377 |
DTSTAMP:20220301T030012Z |
|
378 |
DTSTART;VALUE=DATE:20230211 |
|
379 |
DTEND;VALUE=DATE:20230227 |
|
380 |
SUMMARY:Vacances d'Hiver |
|
381 |
UID:20220301T030126Z-Zone-B@data.education.gouv.fr |
|
382 |
LOCATION: |
|
383 |
DESCRIPTION:Vacances d'Hiver |
|
384 |
TRANSP:TRANSPARENT |
|
385 |
END:VEVENT |
|
386 |
BEGIN:VEVENT |
|
387 |
DTSTAMP:20220301T030012Z |
|
388 |
DTSTART;VALUE=DATE:20230415 |
|
389 |
DTEND;VALUE=DATE:20230502 |
|
390 |
SUMMARY:Vacances de Printemps |
|
391 |
UID:20220301T030127Z-Zone-B@data.education.gouv.fr |
|
392 |
LOCATION: |
|
393 |
DESCRIPTION:Vacances de Printemps |
|
394 |
TRANSP:TRANSPARENT |
|
395 |
END:VEVENT |
|
396 |
BEGIN:VEVENT |
|
397 |
DTSTAMP:20220301T030012Z |
|
398 |
DTSTART;VALUE=DATE:20230518 |
|
399 |
DTEND;VALUE=DATE:20230522 |
|
400 |
SUMMARY:Pont de l'Ascension |
|
401 |
UID:20220301T030128Z-Zone-B@data.education.gouv.fr |
|
402 |
LOCATION: |
|
403 |
DESCRIPTION:Pont de l'Ascension |
|
404 |
TRANSP:TRANSPARENT |
|
405 |
END:VEVENT |
|
406 |
BEGIN:VEVENT |
|
407 |
DTSTAMP:20220301T030012Z |
|
408 |
DTSTART;VALUE=DATE:20230708 |
|
409 |
DTEND;VALUE=DATE:20230708 |
|
410 |
SUMMARY:Début des Vacances d'Été |
|
411 |
UID:20220301T030129Z-Zone-B@data.education.gouv.fr |
|
412 |
LOCATION: |
|
413 |
DESCRIPTION:Début des Vacances d'Été |
|
414 |
TRANSP:TRANSPARENT |
|
415 |
END:VEVENT |
|
416 |
END:VCALENDAR |
tests/test_holidays.py | ||
---|---|---|
1 |
import os |
|
2 | ||
3 |
import pytest |
|
4 |
import vobject |
|
5 |
from httmock import HTTMock, with_httmock |
|
6 | ||
7 |
from passerelle.apps.holidays.models import Holidays |
|
8 | ||
9 |
from .test_manager import login |
|
10 | ||
11 |
pytestmark = pytest.mark.django_db |
|
12 | ||
13 |
with open(os.path.join(os.path.dirname(__file__), 'data/holidays/Zone-A.ics')) as fd: |
|
14 |
RESPONSE_ZONE_A = fd.read() |
|
15 | ||
16 |
with open(os.path.join(os.path.dirname(__file__), 'data/holidays/Zone-B.ics')) as fd: |
|
17 |
RESPONSE_ZONE_B = fd.read() |
|
18 | ||
19 | ||
20 |
def ics_data(url, request): |
|
21 |
if url.path == 'https://fr.ftp.opendatasoft.com/openscol/fr-en-calendrier-scolaire/Zone-A.ics': |
|
22 |
return {'content': RESPONSE_ZONE_A, 'request': request, 'status_code': 200} |
|
23 |
if url.path == 'https://fr.ftp.opendatasoft.com/openscol/fr-en-calendrier-scolaire/Zone-B.ics': |
|
24 |
return {'content': RESPONSE_ZONE_B, 'request': request, 'status_code': 200} |
|
25 | ||
26 | ||
27 |
@with_httmock(ics_data) |
|
28 |
def test_holidays_ics(app): |
|
29 |
connector = Holidays.objects.create(slug='test', zone='a', holidays=[]) |
|
30 | ||
31 |
resp = app.get('/holidays/test/holidays.ics') |
|
32 |
calendar = vobject.readOne(resp.text) |
|
33 |
assert not 'vevent' in calendar.contents |
|
34 | ||
35 |
connector.holidays.append('winter_holidays') |
|
36 |
connector.save() |
|
37 | ||
38 |
resp = app.get('/holidays/test/holidays.ics') |
|
39 |
calendar = vobject.readOne(resp.text) |
|
40 |
first_event = calendar.contents['vevent'][0] |
|
41 |
assert first_event.uid.value == 'winter_holidays-2018' |
|
42 |
assert first_event.summary.value == 'Vacances d’Hiver' |
|
43 |
assert first_event.categories.value == ['winter_holidays'] |
|
44 |
assert str(first_event.dtstart.value) == '2018-02-10' |
|
45 |
assert str(first_event.dtend.value) == '2018-02-26' |
|
46 | ||
47 |
for i, event in enumerate(calendar.contents['vevent'][1:], start=2019): |
|
48 |
assert event.uid.value == 'winter_holidays-%s' % i |
|
49 |
assert event.summary.value == 'Vacances d’Hiver' |
|
50 |
assert event.categories.value == ['winter_holidays'] |
|
51 | ||
52 |
connector.zone = 'b' |
|
53 |
connector.save() |
|
54 | ||
55 |
resp = app.get('/holidays/test/holidays.ics') |
|
56 |
calendar = vobject.readOne(resp.text) |
|
57 |
first_event = calendar.contents['vevent'][0] |
|
58 |
assert first_event.uid.value == 'winter_holidays-2018' |
|
59 |
assert str(first_event.dtstart.value) == '2018-02-24' |
|
60 |
assert str(first_event.dtend.value) == '2018-03-12' |
|
61 | ||
62 |
connector.holidays.append('summer_holidays') |
|
63 |
connector.save() |
|
64 | ||
65 |
resp = app.get('/holidays/test/holidays.ics') |
|
66 |
calendar = vobject.readOne(resp.text) |
|
67 |
assert calendar.contents['vevent'][0].uid.value == 'winter_holidays-2018' |
|
68 |
first_summer_event = next(x for x in calendar.contents['vevent'] if x.uid.value.startswith('summer')) |
|
69 |
assert first_summer_event.uid.value == 'summer_holidays-2018' |
|
70 |
assert first_summer_event.summary.value == 'Vacances d’Été' |
|
71 |
assert first_summer_event.categories.value == ['summer_holidays'] |
|
72 |
assert str(first_summer_event.dtstart.value) == '2018-07-07' |
|
73 |
assert str(first_summer_event.dtend.value) == '2018-09-03' |
|
74 | ||
75 |
connector.holidays = [ |
|
76 |
'winter_holidays', |
|
77 |
'spring_holidays', |
|
78 |
'summer_holidays', |
|
79 |
'all_saints_holidays', |
|
80 |
'christmas_holidays', |
|
81 |
] |
|
82 |
connector.save() |
|
83 | ||
84 |
resp = app.get('/holidays/test/holidays.ics') |
|
85 |
calendar = vobject.readOne(resp.text) |
|
86 |
holiday_ids = {x.categories.value[0] for x in calendar.contents['vevent']} |
|
87 |
assert all(holiday_id in holiday_ids for holiday_id in connector.holidays) |
|
88 | ||
89 | ||
90 |
def test_holidays_ics_invalid_responses(app): |
|
91 |
Holidays.objects.create(slug='test', zone='a', holidays=[]) |
|
92 | ||
93 |
def server_error(url, request): |
|
94 |
return {'content': 'error', 'status_code': 500} |
|
95 | ||
96 |
with HTTMock(server_error): |
|
97 |
resp = app.get('/holidays/test/holidays.ics') |
|
98 |
assert resp.json['err'] == 1 |
|
99 |
assert 'Error while getting ICS file' in resp.json['err_desc'] |
|
100 | ||
101 |
def invalid_file(url, request): |
|
102 |
return {'content': 'invalid', 'status_code': 200} |
|
103 | ||
104 |
with HTTMock(invalid_file): |
|
105 |
resp = app.get('/holidays/test/holidays.ics') |
|
106 |
assert resp.json['err'] == 1 |
|
107 |
assert 'Invalid ICS file' in resp.json['err_desc'] |
|
108 | ||
109 |
def empty_file(url, request): |
|
110 |
return { |
|
111 |
'content': 'BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//PYVOBJECT//NONSGML Version 1//EN\r\nEND:VCALENDAR\r\n', |
|
112 |
'status_code': 200, |
|
113 |
} |
|
114 | ||
115 |
with HTTMock(empty_file): |
|
116 |
resp = app.get('/holidays/test/holidays.ics') |
|
117 |
assert resp.json['err'] == 1 |
|
118 |
assert 'ICS file does not contain events' in resp.json['err_desc'] |
|
119 | ||
120 | ||
121 |
def test_holidays_manager(app, admin_user): |
|
122 |
login(app) |
|
123 | ||
124 |
resp = app.get('/manage/holidays/add') |
|
125 |
resp.form['title'] = 'Holidays' |
|
126 |
resp.form['slug'] = 'test' |
|
127 |
resp.form['description'] = 'test' |
|
128 |
resp.form['zone'] = 'c' |
|
129 |
resp.form['holidays'] = ['summer_holidays', 'christmas_holidays'] |
|
130 | ||
131 |
resp = resp.form.submit().follow() |
|
132 |
assert 'Holidays:\n Vacances d’Été, Vacances de Noël' in resp.text |
|
133 |
assert 'Zone:\n C' in resp.text |
|
0 |
- |