Skip to content

Commit e051f71

Browse files
committed
feat: add Kenya holiday provider (#414)
Adds a holiday provider for Kenya covering the public holidays established by the Public Holidays Act (Cap. 110), including the Sunday-to-Monday substitution rule of Section 4 and the historical evolution of the October holidays (Kenyatta Day/Mashujaa Day and Moi Day/Utamaduni Day/Mazingira Day). The Islamic holidays Idd-ul-Fitr and Idd-ul-Azha are not included yet as their dates depend on the sighting of the moon, following the same approach as the Turkey and Iran providers. Signed-off-by: d-takeuchi <kuronk.kuro3@gmail.com>
1 parent 3b78b42 commit e051f71

18 files changed

Lines changed: 1653 additions & 0 deletions

phpunit.xml.dist

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,10 @@
114114
<testsuite name="Japan">
115115
<directory>./tests/Japan</directory>
116116
</testsuite>
117+
<!-- Test Suite for holidays in Kenya -->
118+
<testsuite name="Kenya">
119+
<directory>./tests/Kenya</directory>
120+
</testsuite>
117121
<!-- Test Suite for holidays in Latvia -->
118122
<testsuite name="Latvia">
119123
<directory>./tests/Latvia</directory>

src/Yasumi/Provider/Kenya.php

Lines changed: 316 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,316 @@
1+
<?php
2+
3+
declare(strict_types = 1);
4+
5+
/**
6+
* This file is part of the 'Yasumi' package.
7+
*
8+
* The easy PHP Library for calculating holidays.
9+
*
10+
* Copyright (c) 2015 - 2026 AzuyaLabs
11+
*
12+
* For the full copyright and license information, please view the LICENSE
13+
* file that was distributed with this source code.
14+
*
15+
* @author Sacha Telgenhof <me at sachatelgenhof dot com>
16+
*/
17+
18+
namespace Yasumi\Provider;
19+
20+
use Yasumi\Exception\UnknownLocaleException;
21+
use Yasumi\Holiday;
22+
use Yasumi\SubstituteHoliday;
23+
24+
/**
25+
* Provider for all holidays in Kenya.
26+
*
27+
* Kenya's public holidays are established by the Public Holidays Act (Cap. 110).
28+
* Section 4 of the Act determines that whenever a public holiday falls on a Sunday,
29+
* the first succeeding day that is not itself a public holiday shall be a public
30+
* holiday.
31+
*
32+
* Note: The Islamic holidays Idd-ul-Fitr (Part I of the Schedule) and Idd-ul-Azha
33+
* (Part II of the Schedule) are not part of this provider yet. Their dates depend
34+
* on the sighting of the moon and are gazetted only shortly in advance. Islamic
35+
* holidays are quite complex and at first, an Islamic calendar provider needs to
36+
* be in place.
37+
*
38+
* @see https://en.wikipedia.org/wiki/Public_holidays_in_Kenya
39+
* @see https://new.kenyalaw.org/akn/ke/act/1912/21/
40+
*/
41+
class Kenya extends AbstractProvider
42+
{
43+
use CommonHolidays;
44+
use ChristianHolidays;
45+
46+
/**
47+
* Code to identify this Holiday Provider. Typically, this is the ISO3166
48+
* code corresponding to the respective country or sub-region.
49+
*/
50+
public const ID = 'KE';
51+
52+
/**
53+
* Year in which Kenya became a republic (12 December 1964). This provider
54+
* covers holidays from this year onwards.
55+
*/
56+
public const ESTABLISHMENT_YEAR = 1964;
57+
58+
/**
59+
* Initialize holidays for Kenya.
60+
*
61+
* @throws \InvalidArgumentException
62+
* @throws UnknownLocaleException
63+
* @throws \Exception
64+
*/
65+
public function initialize(): void
66+
{
67+
$this->timezone = 'Africa/Nairobi';
68+
69+
if ($this->year < self::ESTABLISHMENT_YEAR) {
70+
return;
71+
}
72+
73+
// Add common holidays
74+
$this->addHoliday($this->newYearsDay($this->year, $this->timezone, $this->locale));
75+
$this->addHoliday($this->internationalWorkersDay($this->year, $this->timezone, $this->locale)); // Labour Day
76+
77+
// Add common Christian holidays
78+
$this->addHoliday($this->goodFriday($this->year, $this->timezone, $this->locale));
79+
$this->addHoliday($this->easterMonday($this->year, $this->timezone, $this->locale));
80+
$this->addHoliday($this->christmasDay($this->year, $this->timezone, $this->locale));
81+
$this->addHoliday($this->secondChristmasDay($this->year, $this->timezone, $this->locale)); // Boxing Day
82+
83+
// Calculate other holidays
84+
$this->calculateMadarakaDay();
85+
$this->calculateMoiDay();
86+
$this->calculateUtamaduniDay();
87+
$this->calculateMazingiraDay();
88+
$this->calculateKenyattaDay();
89+
$this->calculateMashujaaDay();
90+
$this->calculateJamhuriDay();
91+
92+
// Determine whether any of the holidays is substituted on another day
93+
$this->calculateSubstituteHolidays();
94+
}
95+
96+
/**
97+
* The source of the holidays.
98+
*
99+
* @return string[] The source URLs
100+
*/
101+
public function getSources(): array
102+
{
103+
return [
104+
'https://en.wikipedia.org/wiki/Public_holidays_in_Kenya',
105+
'https://new.kenyalaw.org/akn/ke/act/1912/21/',
106+
];
107+
}
108+
109+
/**
110+
* Madaraka Day.
111+
*
112+
* "Siku ya Madaraka". Commemorates the day Kenya attained internal
113+
* self-rule on 1 June 1963, preceding full independence.
114+
*
115+
* @see https://en.wikipedia.org/wiki/Madaraka_Day
116+
*
117+
* @throws \Exception
118+
*/
119+
protected function calculateMadarakaDay(): void
120+
{
121+
$this->addHoliday(new Holiday(
122+
'madarakaDay',
123+
['en' => 'Madaraka Day', 'sw' => 'Siku ya Madaraka'],
124+
new \DateTime("{$this->year}-06-01", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
125+
$this->locale
126+
));
127+
}
128+
129+
/**
130+
* Moi Day.
131+
*
132+
* "Siku ya Moi". Honoured the second president, Daniel arap Moi. First
133+
* observed on 10 October 1989 and removed from the list of public holidays
134+
* following the promulgation of the Constitution of Kenya in August 2010.
135+
* On 8 November 2017 the High Court ruled that its removal violated the
136+
* Public Holidays Act, restoring the holiday as of 2018. In 2020 it was
137+
* renamed Utamaduni Day.
138+
*
139+
* @see https://en.wikipedia.org/wiki/Moi_Day
140+
*
141+
* @throws \Exception
142+
*/
143+
protected function calculateMoiDay(): void
144+
{
145+
if (($this->year >= 1989 && $this->year <= 2009) || 2018 === $this->year || 2019 === $this->year) {
146+
$this->addHoliday(new Holiday(
147+
'moiDay',
148+
['en' => 'Moi Day', 'sw' => 'Siku ya Moi'],
149+
new \DateTime("{$this->year}-10-10", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
150+
$this->locale
151+
));
152+
}
153+
}
154+
155+
/**
156+
* Utamaduni Day.
157+
*
158+
* "Siku ya Utamaduni" (Culture Day). In 2020, Moi Day was renamed
159+
* Utamaduni Day to celebrate Kenya's rich cultural diversity. Renamed
160+
* Mazingira Day in 2024.
161+
*
162+
* @see https://en.wikipedia.org/wiki/Mazingira_Day
163+
*
164+
* @throws \Exception
165+
*/
166+
protected function calculateUtamaduniDay(): void
167+
{
168+
if ($this->year >= 2020 && $this->year <= 2023) {
169+
$this->addHoliday(new Holiday(
170+
'utamaduniDay',
171+
['en' => 'Utamaduni Day', 'sw' => 'Siku ya Utamaduni'],
172+
new \DateTime("{$this->year}-10-10", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
173+
$this->locale
174+
));
175+
}
176+
}
177+
178+
/**
179+
* Mazingira Day.
180+
*
181+
* "Siku ya Mazingira" (Environment Day). Utamaduni Day was renamed
182+
* Mazingira Day by the Statute Law (Miscellaneous Amendments) Act, 2024,
183+
* assented to on 24 April 2024. The day is dedicated to environmental
184+
* conservation activities such as tree planting.
185+
*
186+
* @see https://en.wikipedia.org/wiki/Mazingira_Day
187+
*
188+
* @throws \Exception
189+
*/
190+
protected function calculateMazingiraDay(): void
191+
{
192+
if ($this->year >= 2024) {
193+
$this->addHoliday(new Holiday(
194+
'mazingiraDay',
195+
['en' => 'Mazingira Day', 'sw' => 'Siku ya Mazingira'],
196+
new \DateTime("{$this->year}-10-10", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
197+
$this->locale
198+
));
199+
}
200+
}
201+
202+
/**
203+
* Kenyatta Day.
204+
*
205+
* "Siku ya Kenyatta". Commemorated the arrest of the Kapenguria Six,
206+
* among them Jomo Kenyatta, on 20 October 1952. Renamed Mashujaa Day
207+
* following the promulgation of the Constitution of Kenya in August 2010.
208+
*
209+
* @see https://en.wikipedia.org/wiki/Mashujaa_Day
210+
*
211+
* @throws \Exception
212+
*/
213+
protected function calculateKenyattaDay(): void
214+
{
215+
if ($this->year <= 2009) {
216+
$this->addHoliday(new Holiday(
217+
'kenyattaDay',
218+
['en' => 'Kenyatta Day', 'sw' => 'Siku ya Kenyatta'],
219+
new \DateTime("{$this->year}-10-20", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
220+
$this->locale
221+
));
222+
}
223+
}
224+
225+
/**
226+
* Mashujaa Day.
227+
*
228+
* "Siku ya Mashujaa" (Heroes' Day). Honours all those who contributed
229+
* towards the struggle for Kenya's independence or positively contributed
230+
* to post-independence Kenya. Known as Kenyatta Day until the promulgation
231+
* of the Constitution of Kenya in August 2010.
232+
*
233+
* @see https://en.wikipedia.org/wiki/Mashujaa_Day
234+
*
235+
* @throws \Exception
236+
*/
237+
protected function calculateMashujaaDay(): void
238+
{
239+
if ($this->year >= 2010) {
240+
$this->addHoliday(new Holiday(
241+
'mashujaaDay',
242+
['en' => 'Mashujaa Day', 'sw' => 'Siku ya Mashujaa'],
243+
new \DateTime("{$this->year}-10-20", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
244+
$this->locale
245+
));
246+
}
247+
}
248+
249+
/**
250+
* Jamhuri Day.
251+
*
252+
* "Siku ya Jamhuri" (Republic Day). Commemorates the day Kenya was
253+
* admitted into the Commonwealth as a republic on 12 December 1964, and
254+
* the day Kenya obtained its independence on 12 December 1963.
255+
*
256+
* @see https://en.wikipedia.org/wiki/Jamhuri_Day
257+
*
258+
* @throws \Exception
259+
*/
260+
protected function calculateJamhuriDay(): void
261+
{
262+
$this->addHoliday(new Holiday(
263+
'jamhuriDay',
264+
['en' => 'Jamhuri Day', 'sw' => 'Siku ya Jamhuri'],
265+
new \DateTime("{$this->year}-12-12", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
266+
$this->locale
267+
));
268+
}
269+
270+
/**
271+
* Calculate substitute holidays.
272+
*
273+
* Section 4 of the Public Holidays Act (Cap. 110) determines that whenever
274+
* a public holiday falls on a Sunday, the first succeeding day that is not
275+
* itself a public holiday shall be a public holiday. For example, when
276+
* Christmas Day falls on a Sunday, the substitute day is Tuesday 27
277+
* December, as Monday 26 December is already a public holiday (Boxing Day).
278+
*
279+
* @throws \InvalidArgumentException
280+
* @throws UnknownLocaleException
281+
* @throws \Exception
282+
*/
283+
protected function calculateSubstituteHolidays(): void
284+
{
285+
$holidayDates = [];
286+
foreach ($this->getHolidays() as $holiday) {
287+
$holidayDates[$holiday->format('Y-m-d')] = true;
288+
}
289+
290+
// Loop through all defined holidays
291+
foreach ($this->getHolidays() as $holiday) {
292+
if (! $holiday instanceof Holiday) {
293+
continue;
294+
}
295+
296+
// Substitute holiday is only given when the holiday falls on a Sunday
297+
if (0 !== (int) $holiday->format('w')) {
298+
continue;
299+
}
300+
301+
$date = clone $holiday;
302+
do {
303+
$date->add(new \DateInterval('P1D'));
304+
} while (isset($holidayDates[$date->format('Y-m-d')]));
305+
306+
$holidayDates[$date->format('Y-m-d')] = true;
307+
308+
$this->addHoliday(new SubstituteHoliday(
309+
$holiday,
310+
[],
311+
$date,
312+
$this->locale
313+
));
314+
}
315+
}
316+
}

src/Yasumi/data/translations/internationalWorkersDay.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
'de' => 'Tag der Arbeit',
2626
'de_AT' => 'Staatsfeiertag',
2727
'el' => 'Εργατική Πρωτομαγιά',
28+
'en_KE' => 'Labour Day',
2829
'en_US' => 'International Workers’ Day',
2930
'en_ZA' => 'Workers’ Day',
3031
'es' => 'Día del Trabajador',

0 commit comments

Comments
 (0)