1# -*- coding: utf-8 -*-
2# Copyright (c) 2017-present, Facebook, Inc.
3# All rights reserved.
4#
5# This source code is licensed under the BSD-style license found in the
6# LICENSE file in the root directory of this source tree. An additional grant
7# of patent rights can be found in the PATENTS file in the same directory.
8
9from __future__ import absolute_import, division, print_function
10
11import warnings
12from calendar import Calendar, MONDAY
13from datetime import date, timedelta
14
15from convertdate.islamic import from_gregorian, to_gregorian
16from holidays import WEEKEND, HolidayBase, easter, rd
17from lunardate import LunarDate
18
19
20# Official public holidays at a country level
21# ------------ Holidays in Brazil---------------------
22class Brazil(HolidayBase):
23    """
24    Implement public holidays in Brazil
25
26    Reference:
27    https://en.wikipedia.org/wiki/Public_holidays_in_Brazil
28    """
29
30    def __init__(self, **kwargs):
31        self.country = "BR"
32        HolidayBase.__init__(self, **kwargs)
33
34    def _populate(self, year):
35        # New Year's Day
36        if not self.observed and date(year, 1, 1).weekday() in WEEKEND:
37            pass
38        else:
39            self[date(year, 1, 1)] = "New Year's Day"
40
41        # Tiradentes
42        self[date(year, 4, 21)] = "Tiradentes"
43
44        # Worker's Day
45        self[date(year, 5, 1)] = "Worker's Day"
46
47        # Independence Day
48        self[date(year, 9, 7)] = "Independence Day"
49
50        # Our Lady of the Apparition
51        self[date(year, 10, 12)] = "Our Lady of the Apparition"
52
53        # All Souls' Day
54        self[date(year, 11, 2)] = "All Souls' Day"
55
56        # Republic Proclamation Day
57        self[date(year, 11, 5)] = "Republic Proclamation Day"
58
59        # Christmas
60        self[date(year, 12, 25)] = "Christmas"
61
62
63class BR(Brazil):
64    pass
65
66
67# ------------ Holidays in Indonesia---------------------
68class Indonesia(HolidayBase):
69    """
70    Implement public holidays in Indonesia
71
72    Reference:
73    https://en.wikipedia.org/wiki/Public_holidays_in_Indonesia
74
75    Please note: Indonesia is a multi-cultural community and we only implement
76    the national wide public holidays.
77    """
78
79    def __init__(self, **kwargs):
80        self.country = "ID"
81        HolidayBase.__init__(self, **kwargs)
82
83    def _populate(self, year):
84        # New Year's Day
85        if not self.observed and date(year, 1, 1).weekday() in WEEKEND:
86            pass
87        else:
88            self[date(year, 1, 1)] = "New Year's Day"
89
90        # Chinese New Year/ Spring Festival
91        name = "Chinese New Year"
92        for offset in range(-1, 2, 1):
93            ds = LunarDate(year + offset, 1, 1).toSolarDate()
94            if ds.year == year:
95                self[ds] = name
96
97        # Day of Silence / Nyepi
98        # Note:
99        # This holiday is determined by Balinese calendar, which is not currently
100        # available. Only hard coded version of this holiday from 2009 to 2019
101        # is available.
102        warning_msg = "We only support Nyepi holiday from 2009 to 2019"
103        warnings.warn(warning_msg, Warning)
104
105        name = "Day of Silence/ Nyepi"
106        if year == 2009:
107            self[date(year, 3, 26)] = name
108        elif year == 2010:
109            self[date(year, 3, 16)] = name
110        elif year == 2011:
111            self[date(year, 3, 5)] = name
112        elif year == 2012:
113            self[date(year, 3, 23)] = name
114        elif year == 2013:
115            self[date(year, 3, 12)] = name
116        elif year == 2014:
117            self[date(year, 3, 31)] = name
118        elif year == 2015:
119            self[date(year, 3, 21)] = name
120        elif year == 2016:
121            self[date(year, 3, 9)] = name
122        elif year == 2017:
123            self[date(year, 3, 28)] = name
124        elif year == 2018:
125            self[date(year, 3, 17)] = name
126        elif year == 2019:
127            self[date(year, 3, 7)] = name
128        else:
129            pass
130
131        # Ascension of the Prophet
132        name = "Ascension of the Prophet"
133        for offset in range(-1, 2, 1):
134            islam_year = from_gregorian(year + offset, 3, 17)[0]
135            y, m, d = to_gregorian(islam_year, 7, 27)
136            if y == year:
137                self[date(y, m, d)] = name
138
139        # Labor Day
140        name = "Labor Day"
141        self[date(year, 5, 1)] = name
142
143        # Ascension of Jesus Christ
144        name = "Ascension of Jesus"
145        for offset in range(-1, 2, 1):
146            ds = easter(year + offset) + rd(days=+39)
147            if ds.year == year:
148                self[ds] = name
149
150        # Buddha's Birthday
151        name = "Buddha's Birthday"
152        for offset in range(-1, 2, 1):
153            ds = LunarDate(year + offset, 4, 15).toSolarDate()
154            if ds.year == year:
155                self[ds] = name
156
157        # Pancasila Day, since 2017
158        if year >= 2017:
159            name = "Pancasila Day"
160            self[date(year, 6, 1)] = name
161
162        # Eid al-Fitr
163        name = "Eid al-Fitr"
164        for offset in range(-1, 2, 1):
165            islam_year = from_gregorian(year + offset, 6, 15)[0]
166            y1, m1, d1 = to_gregorian(islam_year, 10, 1)
167            y2, m2, d2 = to_gregorian(islam_year, 10, 2)
168            if y1 == year:
169                self[date(y1, m2, d2)] = name
170            if y2 == year:
171                self[date(y2, m2, d2)] = name
172
173        # Independence Day
174        name = "Independence Day"
175        self[date(year, 8, 17)] = name
176
177        # Feast of the Sacrifice
178        name = "Feast of the Sacrifice"
179        for offset in range(-1, 2, 1):
180            islam_year = from_gregorian(year + offset, 8, 22)[0]
181            y, m, d = to_gregorian(islam_year, 12, 10)
182            if y == year:
183                self[date(y, m, d)] = name
184
185        # Islamic New Year
186        name = "Islamic New Year"
187        for offset in range(-1, 2, 1):
188            islam_year = from_gregorian(year + offset, 9, 11)[0]
189            y, m, d = to_gregorian(islam_year + 1, 1, 1)
190            if y == year:
191                self[date(y, m, d)] = name
192
193        # Birth of the Prophet
194        name = "Birth of the Prophet"
195        for offset in range(-1, 2, 1):
196            islam_year = from_gregorian(year + offset, 11, 20)[0]
197            y, m, d = to_gregorian(islam_year + 1, 3, 12)
198            if y == year:
199                self[date(y, m, d)] = name
200
201        # Christmas
202        self[date(year, 12, 25)] = "Christmas"
203
204
205class ID(Indonesia):
206    pass
207
208
209# ------------ Holidays in India---------------------
210class India(HolidayBase):
211    """
212    Implement public holidays in India
213
214    Reference:
215    https://en.wikipedia.org/wiki/Public_holidays_in_India
216
217    Please note:
218    India is a culturally diverse and fervent society, celebrate various
219    holidays and festivals. We only implement the holidays that **all states
220    and territories** celebrate.
221    """
222
223    def __init__(self, **kwargs):
224        self.country = "IN"
225        HolidayBase.__init__(self, **kwargs)
226
227    def _populate(self, year):
228        # --------------------------------
229        # Three national days
230        #     Republic Day
231        #     Independence Day
232        #     Gandhi Jayanti
233        # --------------------------------
234        # Republic Day
235        name = "Republic Day"
236        self[date(year, 1, 26)] = name
237
238        # Independence Day
239        name = "Independence Day"
240        self[date(year, 8, 15)] = name
241
242        # Gandhi Jayanti
243        name = "Gandhi Jayanti"
244        self[date(year, 10, 2)] = name
245        # --------------------------------
246        # Hindo holidays
247        #     Diwali
248        #     Holi
249        # --------------------------------
250
251        # Diwali, Holi
252        # http://www.theholidayspot.com/diwali/calendar.htm
253        # https://www.timeanddate.com/holidays/india/diwali?starty=
254        # https://www.infoplease.com/calendar-holidays/major-holidays/
255        warning_msg = "We only support Diwali and Holi holidays from 2010 to 2025"
256        warnings.warn(warning_msg, Warning)
257        name1 = "Diwali"
258        name2 = "Holi"
259        if year == 2010:
260            self[date(year, 12, 5)] = name1
261            self[date(year, 2, 28)] = name2
262        elif year == 2011:
263            self[date(year, 10, 26)] = name1
264            self[date(year, 3, 19)] = name2
265        elif year == 2012:
266            self[date(year, 11, 13)] = name1
267            self[date(year, 3, 8)] = name2
268        elif year == 2013:
269            self[date(year, 11, 3)] = name1
270            self[date(year, 3, 26)] = name2
271        elif year == 2014:
272            self[date(year, 10, 23)] = name1
273            self[date(year, 3, 17)] = name2
274        elif year == 2015:
275            self[date(year, 11, 11)] = name1
276            self[date(year, 3, 6)] = name2
277        elif year == 2016:
278            self[date(year, 10, 30)] = name1
279            self[date(year, 3, 24)] = name2
280        elif year == 2017:
281            self[date(year, 10, 19)] = name1
282            self[date(year, 3, 13)] = name2
283        elif year == 2018:
284            self[date(year, 11, 7)] = name1
285            self[date(year, 3, 2)] = name2
286        elif year == 2019:
287            self[date(year, 10, 27)] = name1
288            self[date(year, 3, 21)] = name2
289        elif year == 2020:
290            self[date(year, 11, 14)] = name1
291            self[date(year, 3, 9)] = name2
292        elif year == 2021:
293            self[date(year, 11, 4)] = name1
294            self[date(year, 3, 28)] = name2
295        elif year == 2022:
296            self[date(year, 10, 24)] = name1
297            self[date(year, 3, 18)] = name2
298        elif year == 2023:
299            self[date(year, 10, 12)] = name1
300            self[date(year, 3, 7)] = name2
301        elif year == 2024:
302            self[date(year, 11, 1)] = name1
303            self[date(year, 3, 25)] = name2
304        elif year == 2025:
305            self[date(year, 10, 21)] = name1
306            self[date(year, 3, 14)] = name2
307        else:
308            pass
309
310        # --------------------------------
311        # Islamic holidays
312        #     Day of Ashura
313        #     Mawlid
314        #     Eid ul-Fitr
315        #     Eid al-Adha
316        # --------------------------------
317
318        # Day of Ashura
319        # 10th day of 1st Islamic month
320        name = "Day of Ashura"
321        for offset in range(-1, 2, 1):
322            islam_year = from_gregorian(year + offset, 10, 1)[0]
323            y, m, d = to_gregorian(islam_year, 1, 10)
324            if y == year:
325                self[date(y, m, d)] = name
326
327        # Mawlid, Birth of the Prophet
328        # 12th day of 3rd Islamic month
329        name = "Mawlid"
330        for offset in range(-1, 2, 1):
331            islam_year = from_gregorian(year + offset, 11, 20)[0]
332            y, m, d = to_gregorian(islam_year, 3, 12)
333            if y == year:
334                self[date(y, m, d)] = name
335
336        # Eid ul-Fitr
337        # 1st and 2nd day of 10th Islamic month
338        name = "Eid al-Fitr"
339        for offset in range(-1, 2, 1):
340            islam_year = from_gregorian(year + offset, 6, 15)[0]
341            y1, m1, d1 = to_gregorian(islam_year, 10, 1)
342            y2, m2, d2 = to_gregorian(islam_year, 10, 2)
343            if y1 == year:
344                self[date(y1, m1, d1)] = name
345            if y2 == year:
346                self[date(y2, m2, d2)] = name
347
348        # Eid al-Adha, i.e., Feast of the Sacrifice
349        name = "Feast of the Sacrifice"
350        for offset in range(-1, 2, 1):
351            islam_year = from_gregorian(year + offset, 8, 22)[0]
352            y, m, d = to_gregorian(islam_year, 12, 10)
353            if y == year:
354                self[date(y, m, d)] = name
355
356        # --------------------------------
357        # Christian holidays
358        #    New Year, Palm Sunday,
359        #    Maundy Thursday
360        #    Good Friday
361        #    Easter Sunday
362        #    Feast of Pentecost
363        #    Fest of St. Theresa of Calcutta
364        #    Feast of the Blessed Virgin
365        #    All Saints Day
366        #    All Souls Day
367        #    Christmas Day
368        #    Boxing Day
369        #    Feast of Holy Family
370        # --------------------------------
371        # New Year's Day
372        self[date(year, 1, 1)] = "New Year's Day"
373
374        # Palm Sunday
375        name = "Palm Sunday"
376        for offset in range(-1, 2, 1):
377            ds = easter(year + offset) - rd(days=7)
378            if ds.year == year:
379                self[ds] = name
380
381        # Maundy Thursday
382        name = "Maundy Thursday"
383        for offset in range(-1, 2, 1):
384            ds = easter(year + offset) - rd(days=3)
385            if ds.year == year:
386                self[ds] = name
387
388        # Good Friday
389        name = "Good Friday"
390        for offset in range(-1, 2, 1):
391            ds = easter(year + offset) - rd(days=2)
392            if ds.year == year:
393                self[ds] = name
394
395        # Easter Sunday
396        name = "Easter Sunday"
397        for offset in range(-1, 2, 1):
398            ds = easter(year + offset)
399            if ds.year == year:
400                self[ds] = name
401
402        # Feast of Pentecost
403        name = "Feast of Pentecost"
404        for offset in range(-1, 2, 1):
405            ds = easter(year + offset) + rd(days=49)
406            if ds.year == year:
407                self[ds] = name
408
409        # Fest of St. Theresa of Calcutta
410        name = "Fest of St. Theresa of Calcutta"
411        self[date(year, 9, 5)] = name
412
413        # Feast of the Blessed Virgin
414        name = "Feast of the Blessed Virgin"
415        self[date(year, 9, 8)] = name
416
417        # All Saints Day
418        name = "All Saints Day"
419        self[date(year, 11, 1)] = name
420
421        # All Souls Day
422        name = "All Souls Day"
423        self[date(year, 11, 2)] = name
424
425        # Christmas
426        name = "Christmas Day"
427        self[date(year, 12, 25)] = name
428
429        # Boxing Day
430        name = "Boxing Day"
431        self[date(year, 12, 26)] = name
432
433        # Feast of Holy Family
434        name = "Feast of Holy Family"
435        self[date(year, 12, 30)] = name
436
437
438class IN(India):
439    pass
440
441
442# ------------ Holidays in Malaysia---------------------
443class Malaysia(HolidayBase):
444    """
445    Implement public holidays in Malaysia
446
447    Reference:
448    https://en.wikipedia.org/wiki/Public_holidays_in_Malaysia
449    """
450
451    def __init__(self, **kwargs):
452        self.country = "MY"
453        HolidayBase.__init__(self, **kwargs)
454
455    def _populate(self, year):
456        # New Year's Day
457        name = "New Year's Day"
458        self[date(year, 1, 1)] = name
459
460        # Birthday of Prophet, Mawlid in India
461        # 12th day of 3rd Islamic month
462        name = "Birth of Prophet"
463        for offset in range(-1, 2, 1):
464            islam_year = from_gregorian(year + offset, 11, 20)[0]
465            y, m, d = to_gregorian(islam_year, 3, 12)
466            if y == year:
467                self[date(y, m, d)] = name
468
469        # Chinese New Year
470        name = "Chinese New Year"
471        for offset in range(-1, 2, 1):
472            ds = LunarDate(year + offset, 1, 1).toSolarDate()
473            if ds.year == year:
474                self[ds] = name
475
476        # Tamil New Year
477        # Note: it's not necessarily 04/14
478        # due to the local calendar
479        # other possible dates are 04/13 and 04/15
480        name = "Tamil New Year"
481        self[date(year, 4, 14)] = name
482
483        # Good Friday
484        name = "Good Friday"
485        for offset in range(-1, 2, 1):
486            ds = easter(year + offset) - rd(days=2)
487            if ds.year == year:
488                self[ds] = name
489
490        # Labor Day
491        name = "Labor Day"
492        self[date(year, 5, 1)] = name
493
494        # Buddha's Birthday
495        name = "Wesak Day"
496        for offset in range(-1, 2, 1):
497            ds = LunarDate(year + offset, 4, 15).toSolarDate()
498            if ds.year == year:
499                self[ds] = name
500
501        # King's birthday
502        # https://www.thestar.com.my/news/nation/2017/04/26/
503        # Before 2017: first Saturday of June
504        # 2017-2021: last Saturday of July
505        name = "King's birthday"
506        if year < 2017:
507            c = Calendar(firstweekday=MONDAY)
508            monthcal = c.monthdatescalendar(year, 6)
509
510            l1 = len(monthcal)
511            saturdays = []
512            for i in range(l1):
513                if monthcal[i][5].month == 6:
514                    saturdays.append(monthcal[i][5])
515            self[saturdays[0]] = name
516        elif (year >= 2017) and (year <= 2021):
517            c = Calendar(firstweekday=MONDAY)
518            monthcal = c.monthdatescalendar(year, 7)
519
520            l1 = len(monthcal)
521            saturdays = []
522            for i in range(l1):
523                if monthcal[i][5].month == 7:
524                    saturdays.append(monthcal[i][5])
525            self[saturdays[-1]] = name
526
527        # Eid al-Fitr
528        name = "Eid al-Fitr"
529        for offset in range(-1, 2, 1):
530            islam_year = from_gregorian(year + offset, 6, 15)[0]
531            y1, m1, d1 = to_gregorian(islam_year, 10, 1)
532            y2, m2, d2 = to_gregorian(islam_year, 10, 2)
533            if y1 == year:
534                self[date(y1, m1, d1)] = name
535            if y2 == year:
536                self[date(y2, m2, d2)] = name
537
538        # Malaysia Day
539        name = "Malaysia Day"
540        self[date(year, 9, 16)] = name
541
542        # Feast of the Sacrifice
543        name = "Feast of the Sacrifice"
544        for offset in range(-1, 2, 1):
545            islam_year = from_gregorian(year + offset, 8, 22)[0]
546            y, m, d = to_gregorian(islam_year, 12, 10)
547            if y == year:
548                self[date(y, m, d)] = name
549
550        # First Day of Muharram
551        name = "First Day of Muharram"
552        for offset in range(-1, 2, 1):
553            islam_year = from_gregorian(year + offset, 9, 11)[0]
554            y, m, d = to_gregorian(islam_year + 1, 1, 1)
555            if y == year:
556                self[date(y, m, d)] = name
557
558        # Christmas
559        name = "Christmas Day"
560        self[date(year, 12, 25)] = name
561
562
563class MY(Malaysia):
564    pass
565
566
567# ------------ Holidays in Vietnam---------------------
568class Vietnam(HolidayBase):
569    """
570    Implement public holidays in Vietnam
571
572    Reference:
573    https://en.wikipedia.org/wiki/Public_holidays_in_Vietnam
574    """
575
576    def __init__(self, **kwargs):
577        self.country = "VN"
578        HolidayBase.__init__(self, **kwargs)
579
580    def _populate(self, year):
581        # New Year's Day
582        name = "New Year's Day"
583        self[date(year, 1, 1)] = name
584
585        # Vietnamese New Year
586        name = "Vietnamese New Year"
587        for offset in range(-1, 2, 1):
588            try:
589                ds = LunarDate(year - 1 + offset, 12, 30).toSolarDate()
590            except ValueError:
591                ds = LunarDate(year - 1 + offset, 12, 29).toSolarDate()
592            if ds.year == year:
593                self[ds] = name
594            ds = LunarDate(year + offset, 1, 1).toSolarDate()
595            if ds.year == year:
596                self[ds] = name
597            ds = LunarDate(year + offset, 1, 2).toSolarDate()
598            if ds.year == year:
599                self[ds] = name
600            ds = LunarDate(year + offset, 1, 3).toSolarDate()
601            if ds.year == year:
602                self[ds] = name
603            ds = LunarDate(year + offset, 1, 4).toSolarDate()
604            if ds.year == year:
605                self[ds] = name
606            ds = LunarDate(year + offset, 1, 5).toSolarDate()
607            if ds.year == year:
608                self[ds] = name
609
610        # Hung Kings Commemorations
611        name = "Hung Kings Commemorations"
612        for offset in range(-1, 2, 1):
613            ds = LunarDate(year + offset, 3, 10).toSolarDate()
614            if ds.year == year:
615                self[ds] = name
616
617        # Reunification Day
618        name = "Reunification Day"
619        self[date(year, 4, 30)] = name
620
621        # Labor Day/International Workers' Day
622        name = "Labor Day/International Workers' Day"
623        self[date(year, 5, 1)] = name
624
625        # National Day
626        name = "National Day"
627        self[date(year, 9, 2)] = name
628
629
630class VN(Vietnam):
631    pass
632
633
634# ------------ Holidays in Thailand---------------------
635class Thailand(HolidayBase):
636    """
637    Implement public holidays in Thailand
638
639    Reference:
640    https://en.wikipedia.org/wiki/Public_holidays_in_Thailand
641    """
642
643    def __init__(self, **kwargs):
644        self.country = "TH"
645        HolidayBase.__init__(self, **kwargs)
646
647    def _populate(self, year):
648        # New Year's Day
649        name = "New Year's Day"
650        self[date(year, 1, 1)] = name
651
652        # Magha Pujab
653        # Note:
654        # This holiday is determined by Buddhist calendar, which is not currently
655        # available. Only hard coded version of this holiday from 2016 to 2019
656        # is available.
657
658        name = "Magha Pujab/Makha Bucha"
659        if year == 2016:
660            self[date(year, 2, 22)] = name
661        elif year == 2017:
662            self[date(year, 2, 11)] = name
663        elif year == 2018:
664            self[date(year, 3, 1)] = name
665        elif year == 2019:
666            self[date(year, 2, 19)] = name
667        else:
668            pass
669
670        # Chakri Memorial Day
671        name = "Chakri Memorial Day"
672        april_6 = date(year, 4, 6).weekday()
673        if april_6 == 5:
674            self[date(year, 4, 6 + 2)] = name
675        elif april_6 == 6:
676            self[date(year, 4, 6 + 1)] = name
677        else:
678            self[date(year, 4, 6)] = name
679
680        # Songkran Festival
681        name = "Songkran Festival"
682        self[date(year, 4, 14)] = name
683
684        # Royal Ploughing Ceremony
685        # arbitrary day in May
686
687        # Buddha's Birthday
688        name = "Buddha's Birthday"
689        for offset in range(-1, 2, 1):
690            ds = LunarDate(year + offset, 4, 15).toSolarDate()
691            if ds.year == year:
692                self[ds] = name
693
694        # Coronation Day, removed in 2017
695        name = "Coronation Day"
696        if year < 2017:
697            self[date(year, 5, 5)] = name
698
699        # King Maha Vajiralongkorn's Birthday
700        name = "King Maha Vajiralongkorn's Birthday"
701        self[date(year, 7, 28)] = name
702
703        # Asalha Puja
704        # This is also a Buddha holiday, and we only implement
705        # the hard coded version from 2006 to 2025
706        # reference:
707        # http://www.when-is.com/asalha_puja.asp
708        warning_msg = "We only support Asalha Puja holiday from 2006 to 2025"
709        warnings.warn(warning_msg, Warning)
710        name = "Asalha Puja"
711        if year == 2006:
712            self[date(year, 7, 11)] = name
713        elif year == 2007:
714            self[date(year, 6, 30)] = name
715        elif year == 2008:
716            self[date(year, 7, 18)] = name
717        elif year == 2009:
718            self[date(year, 7, 7)] = name
719        elif year == 2010:
720            self[date(year, 7, 25)] = name
721        elif year == 2011:
722            self[date(year, 7, 15)] = name
723        elif year == 2012:
724            self[date(year, 8, 2)] = name
725        elif year == 2013:
726            self[date(year, 7, 30)] = name
727        elif year == 2014:
728            self[date(year, 7, 13)] = name
729        elif year == 2015:
730            self[date(year, 7, 30)] = name
731        elif year == 2016:
732            self[date(year, 7, 15)] = name
733        elif year == 2017:
734            self[date(year, 7, 9)] = name
735        elif year == 2018:
736            self[date(year, 7, 29)] = name
737        elif year == 2019:
738            self[date(year, 7, 16)] = name
739        elif year == 2020:
740            self[date(year, 7, 5)] = name
741        elif year == 2021:
742            self[date(year, 7, 24)] = name
743        elif year == 2022:
744            self[date(year, 7, 13)] = name
745        elif year == 2023:
746            self[date(year, 7, 3)] = name
747        elif year == 2024:
748            self[date(year, 7, 21)] = name
749        elif year == 2025:
750            self[date(year, 7, 10)] = name
751        else:
752            pass
753
754        # Beginning of Vassa
755        warning_msg = "We only support Vassa holiday from 2006 to 2020"
756        warnings.warn(warning_msg, Warning)
757        name = "Beginning of Vassa"
758        if year == 2006:
759            self[date(year, 7, 12)] = name
760        elif year == 2007:
761            self[date(year, 7, 31)] = name
762        elif year == 2008:
763            self[date(year, 7, 19)] = name
764        elif year == 2009:
765            self[date(year, 7, 8)] = name
766        elif year == 2010:
767            self[date(year, 7, 27)] = name
768        elif year == 2011:
769            self[date(year, 7, 16)] = name
770        elif year == 2012:
771            self[date(year, 8, 3)] = name
772        elif year == 2013:
773            self[date(year, 7, 23)] = name
774        elif year == 2014:
775            self[date(year, 7, 13)] = name
776        elif year == 2015:
777            self[date(year, 8, 1)] = name
778        elif year == 2016:
779            self[date(year, 7, 20)] = name
780        elif year == 2017:
781            self[date(year, 7, 9)] = name
782        elif year == 2018:
783            self[date(year, 7, 28)] = name
784        elif year == 2019:
785            self[date(year, 7, 17)] = name
786        elif year == 2020:
787            self[date(year, 7, 6)] = name
788        else:
789            pass
790
791        # The Queen Sirikit's Birthday
792        name = "The Queen Sirikit's Birthday"
793        self[date(year, 8, 12)] = name
794
795        # Anniversary for the Death of King Bhumibol Adulyadej
796        name = "Anniversary for the Death of King Bhumibol Adulyadej"
797        self[date(year, 10, 13)] = name
798
799        # King Chulalongkorn Day
800        name = "King Chulalongkorn Day"
801        self[date(year, 10, 23)] = name
802
803        # King Bhumibol Adulyadej's Birthday Anniversary
804        name = "King Bhumibol Adulyadej's Birthday Anniversary"
805        self[date(year, 12, 5)] = name
806
807        # Constitution Day
808        name = "Constitution Day"
809        self[date(year, 12, 10)] = name
810
811        # New Year's Eve
812        name = "New Year's Eve"
813        self[date(year, 12, 31)] = name
814
815
816class TH(Thailand):
817    pass
818
819
820# ------------ Holidays in Philippines---------------------
821class Philippines(HolidayBase):
822    """
823    Implement public holidays in Philippines
824
825    Reference:
826    https://en.wikipedia.org/wiki/Public_holidays_in_Thailand
827    """
828
829    def __init__(self, **kwargs):
830        self.country = "PH"
831        HolidayBase.__init__(self, **kwargs)
832
833    def _populate(self, year):
834        # New Year's Day
835        name = "New Year's Day"
836        self[date(year, 1, 1)] = name
837
838        # Maundy Thursday
839        name = "Maundy Thursday"
840        for offset in range(-1, 2, 1):
841            ds = easter(year + offset) - rd(days=3)
842            if ds.year == year:
843                self[ds] = name
844
845        # Good Friday
846        name = "Good Friday"
847        for offset in range(-1, 2, 1):
848            ds = easter(year + offset) - rd(days=2)
849            if ds.year == year:
850                self[ds] = name
851
852        # Day of Valor
853        name = "Day of Valor"
854        self[date(year, 4, 9)] = name
855
856        # Labor Day
857        name = "Labor Day"
858        self[date(year, 5, 1)] = name
859
860        # Independence Day
861        name = "Independence Day"
862        self[date(year, 6, 12)] = name
863
864        # Eid al-Fitr
865        name = "Eid al-Fitr"
866        for offset in range(-1, 2, 1):
867            islam_year = from_gregorian(year + offset, 6, 15)[0]
868            y, m, d = to_gregorian(islam_year, 10, 1)
869            ds = date(y, m, d) - timedelta(days=1)
870            if ds.year == year:
871                self[ds] = name
872
873        # Eid al-Adha, i.e., Feast of the Sacrifice
874        name = "Feast of the Sacrifice"
875        for offset in range(-1, 2, 1):
876            islam_year = from_gregorian(year + offset, 8, 22)[0]
877            y, m, d = to_gregorian(islam_year, 12, 10)
878            if y == year:
879                self[date(y, m, d)] = name
880
881        # National Heroes' Day
882        name = "National Heroes' Day"
883        self[date(year, 8, 27)] = name
884
885        # Bonifacio Day
886        name = "Bonifacio Day"
887        self[date(year, 11, 30)] = name
888
889        # Christmas Day
890        name = "Christmas Day"
891        self[date(year, 12, 25)] = name
892
893        # Rizal Day
894        name = "Rizal Day"
895        self[date(year, 12, 30)] = name
896
897
898class PH(Philippines):
899    pass
900
901
902# ------------ Holidays in Turkey---------------------
903class Turkey(HolidayBase):
904    """
905    Implement public holidays in Turkey
906
907    Reference:
908    https://en.wikipedia.org/wiki/Public_holidays_in_Turkey
909    """
910
911    def __init__(self, **kwargs):
912        self.country = "TU"
913        HolidayBase.__init__(self, **kwargs)
914
915    def _populate(self, year):
916        # New Year's Day
917        name = "New Year's Day"
918        self[date(year, 1, 1)] = name
919
920        # National Sovereignty and Children's Day
921        name = "National Sovereignty and Children's Day	"
922        self[date(year, 4, 23)] = name
923
924        # Labor Day
925        name = "Labor Day"
926        self[date(year, 5, 1)] = name
927
928        # Commemoration of Atatürk, Youth and Sports Day
929        name = u"Commemoration of Atatürk, Youth and Sports Day"
930        self[date(year, 5, 19)] = name
931
932        # Democracy and National Unity Day
933        name = "Democracy and National Unity Day"
934        self[date(year, 7, 15)] = name
935
936        # Victory Day
937        name = "Victory Day"
938        self[date(year, 8, 30)] = name
939
940        # Republic Day
941        name = "Republic Day"
942        self[date(year, 10, 29)] = name
943
944        # Eid al-Fitr
945        name = "Eid al-Fitr"
946        for offset in range(-1, 2, 1):
947            islam_year = from_gregorian(year + offset, 6, 15)[0]
948            y, m, d = to_gregorian(islam_year, 10, 1)
949            ds = date(y, m, d) - timedelta(days=1)
950            if ds.year == year:
951                self[ds] = name
952
953        # Eid al-Adha, i.e., Feast of the Sacrifice
954        name = "Feast of the Sacrifice"
955        for offset in range(-1, 2, 1):
956            islam_year = from_gregorian(year + offset, 8, 22)[0]
957            y, m, d = to_gregorian(islam_year, 12, 10)
958            if y == year:
959                self[date(y, m, d)] = name
960
961
962class TU(Turkey):
963    pass
964
965
966# ------------ Holidays in Pakistan---------------------
967class Pakistan(HolidayBase):
968    """
969    Implement public holidays in Pakistan
970
971    Reference:
972    https://en.wikipedia.org/wiki/Public_holidays_in_Pakistan
973    """
974
975    def __init__(self, **kwargs):
976        self.country = "PK"
977        HolidayBase.__init__(self, **kwargs)
978
979    def _populate(self, year):
980
981        # Kashmir Solidarity Day
982        name = "Kashmir Solidarity Day"
983        self[date(year, 2, 5)] = name
984
985        # Pakistan Day
986        name = "Pakistan Day"
987        self[date(year, 3, 23)] = name
988
989        # Labor Day
990        name = "Labor Day"
991        self[date(year, 5, 1)] = name
992
993        # Independence Day
994        name = "Independence Day"
995        self[date(year, 8, 14)] = name
996
997        # Iqbal Day
998        name = "Iqbal Day"
999        self[date(year, 11, 9)] = name
1000
1001        # Christmas Day
1002        # Also birthday of PK founder
1003        name = "Christmas Day"
1004        self[date(year, 12, 25)] = name
1005
1006        # Eid al-Adha, i.e., Feast of the Sacrifice
1007        name = "Feast of the Sacrifice"
1008        for offset in range(-1, 2, 1):
1009            islam_year = from_gregorian(year + offset, 8, 22)[0]
1010            y1, m1, d1 = to_gregorian(islam_year, 12, 10)
1011            y2, m2, d2 = to_gregorian(islam_year, 12, 11)
1012            y3, m3, d3 = to_gregorian(islam_year, 12, 12)
1013            if y1 == year:
1014                self[date(y1, m1, d1)] = name
1015            if y2 == year:
1016                self[date(y2, m2, d2)] = name
1017            if y3 == year:
1018                self[date(y3, m3, d3)] = name
1019
1020        # Eid al-Fitr
1021        name = "Eid al-Fitr"
1022        for offset in range(-1, 2, 1):
1023            islam_year = from_gregorian(year + offset, 6, 15)[0]
1024            y1, m1, d1 = to_gregorian(islam_year, 10, 1)
1025            y2, m2, d2 = to_gregorian(islam_year, 10, 2)
1026            y3, m3, d3 = to_gregorian(islam_year, 10, 3)
1027            if y1 == year:
1028                self[date(y1, m1, d1)] = name
1029            if y2 == year:
1030                self[date(y2, m2, d2)] = name
1031            if y3 == year:
1032                self[date(y3, m3, d3)] = name
1033
1034        # Mawlid, Birth of the Prophet
1035        # 12th day of 3rd Islamic month
1036        name = "Mawlid"
1037        for offset in range(-1, 2, 1):
1038            islam_year = from_gregorian(year + offset, 11, 20)[0]
1039            y, m, d = to_gregorian(islam_year, 3, 12)
1040            if y == year:
1041                self[date(y, m, d)] = name
1042
1043        # Day of Ashura
1044        # 10th and 11th days of 1st Islamic month
1045        name = "Day of Ashura"
1046        for offset in range(-1, 2, 1):
1047            islam_year = from_gregorian(year + offset, 10, 1)[0]
1048            y1, m1, d1 = to_gregorian(islam_year, 1, 10)
1049            y2, m2, d2 = to_gregorian(islam_year, 1, 11)
1050            if y1 == year:
1051                self[date(y1, m1, d1)] = name
1052            if y2 == year:
1053                self[date(y2, m2, d2)] = name
1054
1055        # Shab e Mairaj
1056        name = "Shab e Mairaj"
1057        for offset in range(-1, 2, 1):
1058            islam_year = from_gregorian(year + offset, 4, 13)[0]
1059            y, m, d = to_gregorian(islam_year, 7, 27)
1060            if y == year:
1061                self[date(y, m, d)] = name
1062
1063        # Defence Day
1064        name = "Defence Day"
1065        self[date(year, 9, 6)] = name
1066
1067        # Death Anniversary of Quaid-e-Azam
1068        name = "Death Anniversary of Quaid-e-Azam"
1069        self[date(year, 9, 11)] = name
1070
1071
1072class PK(Pakistan):
1073    pass
1074
1075
1076# ------------ Holidays in Bangladesh---------------------
1077class Bangladesh(HolidayBase):
1078    """
1079    Implement public holidays in Bangladesh
1080
1081    Reference:
1082    https://en.wikipedia.org/wiki/Public_holidays_in_Bangladesh
1083    """
1084
1085    def __init__(self, **kwargs):
1086        self.country = "BD"
1087        HolidayBase.__init__(self, **kwargs)
1088
1089    def _populate(self, year):
1090
1091        # Language Martyrs' Day
1092        name = "Language Martyrs' Day"
1093        self[date(year, 2, 21)] = name
1094
1095        # Mujib's birthday
1096        name = "Mujib's birthday"
1097        self[date(year, 3, 17)] = name
1098
1099        # Independence Day
1100        name = "Independence Day"
1101        self[date(year, 3, 26)] = name
1102
1103        # Bengali New Year's Day
1104        name = "Bengali New Year's Day"
1105        self[date(year, 4, 14)] = name
1106
1107        # Labor Day, May Day (local name)
1108        name = "Labor Day"
1109        self[date(year, 5, 1)] = name
1110
1111        # National Mourning Day
1112        name = "National Mourning Day"
1113        self[date(year, 8, 15)] = name
1114
1115        # Victory Day
1116        name = "Victory Day"
1117        self[date(year, 12, 16)] = name
1118
1119
1120class BD(Bangladesh):
1121    pass
1122
1123
1124# ------------ Holidays in Egypt---------------------
1125class Egypt(HolidayBase):
1126    """
1127    Implement public holidays in Egypt
1128
1129    Reference:
1130    https://en.wikipedia.org/wiki/Public_holidays_in_Egypt
1131    """
1132
1133    def __init__(self, **kwargs):
1134        self.country = "EG"
1135        HolidayBase.__init__(self, **kwargs)
1136
1137    def _populate(self, year):
1138
1139        # Fixed holidays
1140        # Christmas
1141        name = "Christmas"
1142        self[date(year, 1, 7)] = name
1143
1144        # Revolution Day, after 2011
1145        name = "Revolution Day 2011"
1146        if year <= 2011:
1147            self[date(year, 1, 25)] = name
1148
1149        # Sinai Liberation Day, after 1982
1150        name = "Sinai Liberation Day"
1151        if year <= 1982:
1152            self[date(year, 4, 25)] = name
1153
1154        # Labor Day
1155        name = "Labor Day"
1156        self[date(year, 5, 1)] = name
1157
1158        # Revolution Day
1159        name = "Sinai Liberation Day"
1160        self[date(year, 7, 23)] = name
1161
1162        # Armed Forces Day
1163        name = "Armed Forces Day"
1164        self[date(year, 10, 6)] = name
1165
1166        # Sham El Nessim
1167        # The Monday following Orthodox Easter
1168        name = "Sham El Nessim"
1169        for offset in range(-1, 2, 1):
1170            orthodox_easter = easter(year + offset, method=2)
1171            ds = orthodox_easter + timedelta(days=1)
1172            if ds.year == year:
1173                self[ds] = name
1174
1175        # Islamic New Year
1176        name = "Islamic New Year"
1177        for offset in range(-1, 2, 1):
1178            islam_year = from_gregorian(year + offset, 9, 11)[0]
1179            y, m, d = to_gregorian(islam_year + 1, 1, 1)
1180            if y == year:
1181                self[date(y, m, d)] = name
1182
1183        # Birthday of Prophet, Mawlid in India
1184        # 12th day of 3rd Islamic month
1185        name = "Birth of Prophet"
1186        for offset in range(-1, 2, 1):
1187            islam_year = from_gregorian(year + offset, 11, 20)[0]
1188            y, m, d = to_gregorian(islam_year, 3, 12)
1189            if y == year:
1190                self[date(y, m, d)] = name
1191
1192        # Eid ul-Fitr
1193        # 1st and 2nd day of 10th Islamic month
1194        name = "Eid al-Fitr"
1195        for offset in range(-1, 2, 1):
1196            islam_year = from_gregorian(year + offset, 6, 15)[0]
1197            y1, m1, d1 = to_gregorian(islam_year, 10, 1)
1198            y2, m2, d2 = to_gregorian(islam_year, 10, 2)
1199            y3, m3, d3 = to_gregorian(islam_year, 10, 3)
1200            if y1 == year:
1201                self[date(y1, m1, d1)] = name
1202            if y2 == year:
1203                self[date(y2, m2, d2)] = name
1204            if y3 == year:
1205                self[date(y3, m3, d3)] = name
1206
1207        # Eid al-Adha, i.e., Feast of the Sacrifice
1208        name = "Feast of the Sacrifice"
1209        for offset in range(-1, 2, 1):
1210            islam_year = from_gregorian(year + offset, 8, 22)[0]
1211            y1, m1, d1 = to_gregorian(islam_year, 12, 10)
1212            y2, m2, d2 = to_gregorian(islam_year, 12, 11)
1213            y3, m3, d3 = to_gregorian(islam_year, 12, 12)
1214            y4, m4, d4 = to_gregorian(islam_year, 12, 13)
1215            if y1 == year:
1216                self[date(y1, m1, d1)] = name
1217            if y2 == year:
1218                self[date(y2, m2, d2)] = name
1219            if y3 == year:
1220                self[date(y3, m3, d3)] = name
1221            if y4 == year:
1222                self[date(y4, m4, d4)] = name
1223
1224
1225class EG(Egypt):
1226    pass
1227
1228
1229# ------------ Holidays in China---------------------
1230class China(HolidayBase):
1231    """
1232    Implement public holidays in China
1233
1234    Reference:
1235    https://en.wikipedia.org/wiki/Public_holidays_in_China
1236    """
1237
1238    def __init__(self, **kwargs):
1239        self.country = "CN"
1240        HolidayBase.__init__(self, **kwargs)
1241
1242    def _populate(self, year):
1243        # New Year's Day
1244        name = "New Year's Day"
1245        self[date(year, 1, 1)] = name
1246
1247        # Chinese New Year/ Spring Festival
1248        name = "Chinese New Year"
1249        for offset in range(-1, 2, 1):
1250            ds = LunarDate(year + offset, 1, 1).toSolarDate()
1251            if ds.year == year:
1252                self[ds] = name
1253
1254        # Tomb-Sweeping Day
1255        name = "Tomb-Sweeping Day"
1256        self[date(year, 4, 4)] = name
1257        self[date(year, 4, 5)] = name
1258
1259        # Labor Day
1260        name = "Labor Day"
1261        self[date(year, 5, 1)] = name
1262
1263        # Dragon Boat Festival
1264        name = "Dragon Boat Festival"
1265        for offset in range(-1, 2, 1):
1266            ds = LunarDate(year + offset, 5, 5).toSolarDate()
1267            if ds.year == year:
1268                self[ds] = name
1269
1270        # Mid-Autumn Festival
1271        name = "Mid-Autumn Festival"
1272        for offset in range(-1, 2, 1):
1273            ds = LunarDate(year + offset, 8, 15).toSolarDate()
1274            if ds.year == year:
1275                self[ds] = name
1276
1277        # National Day
1278        name = "National Day"
1279        self[date(year, 10, 1)] = name
1280
1281
1282class CN(China):
1283    pass
1284
1285# ------------ Holidays in Russia---------------------
1286class Russia(HolidayBase):
1287    """
1288    Implement public holidays in Russia
1289
1290    Reference:
1291    https://en.wikipedia.org/wiki/Public_holidays_in_Russia
1292
1293    Please note:
1294    Orthodox Christmas Day is official day off at Russia
1295    But the Dec. 25 Christmas is also celebrated.
1296    """
1297
1298    def __init__(self, **kwargs):
1299        self.country = "RU"
1300        HolidayBase.__init__(self, **kwargs)
1301
1302    def _populate(self, year):
1303        # New Year's Day
1304        name = "New Year's Day"
1305        self[date(year, 1, 1)] = name
1306
1307        # Orthodox Christmas day
1308        name = "Orthodox Christmas Day"
1309        self[date(year, 1, 7)] = name
1310
1311        # Dec. 25 Christmas Day
1312        name = "Christmas Day"
1313        self[date(year, 12, 25)] = name
1314
1315        # Defender of the Fatherland Day
1316        name = "Defender of the Fatherland Day"
1317        self[date(year, 2, 23)] = name
1318
1319        # International Women's Day
1320        name = "International Women's Day"
1321        self[date(year, 3, 8)] = name
1322
1323        # National Flag Day
1324        name = "National Flag Day"
1325        self[date(year, 8, 22)] = name
1326
1327        # Spring and Labour Day
1328        name = "Spring and Labour Day"
1329        self[date(year, 5, 1)] = name
1330
1331        # Victory Day
1332        name = "Victory Day"
1333        self[date(year, 5, 9)] = name
1334
1335        # Russia Day
1336        name = "Russia Day"
1337        self[date(year, 6, 12)] = name
1338
1339        # Unity Day
1340        name = "Unity Day"
1341        self[date(year, 11, 4)] = name
1342
1343
1344class RU(Russia):
1345    pass
1346