SouthKorea::initialize()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 26
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 17
c 1
b 0
f 0
dl 0
loc 26
rs 9.7
cc 2
nc 2
nop 0
1
<?php declare(strict_types=1);
2
3
/**
4
 * This file is part of the Yasumi package.
5
 *
6
 * Copyright (c) 2015 - 2020 AzuyaLabs
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 *
11
 * @author Sacha Telgenhof <[email protected]>
12
 */
13
14
namespace Yasumi\Provider;
15
16
use DateInterval;
17
use DateTime;
18
use Yasumi\Exception\InvalidDateException;
19
use Yasumi\Exception\UnknownLocaleException;
20
use Yasumi\Holiday;
21
use Yasumi\SubstituteHoliday;
22
23
/**
24
 * Provider for all holidays in the South Korea except for election day and temporary public holiday.
25
 *
26
 * @link https://en.wikipedia.org/wiki/Public_holidays_in_South_Korea
27
 */
28
class SouthKorea extends AbstractProvider
29
{
30
    use CommonHolidays, ChristianHolidays;
31
32
    /**
33
     * Code to identify this Holiday Provider. Typically this is the ISO3166 code corresponding to the respective
34
     * country or sub-region.
35
     */
36
    public const ID = 'KR';
37
38
    /**
39
     * Dates in Gregorian calendar of Seollal, Buddha's Birthday, and Chuseok (~ 2050)
40
     *
41
     * The Korean calendar is derived from the Chinese calendar. Although not being an official calendar, the
42
     * traditional Korean calendar is still maintained by the government. The current version is based on China's
43
     * Shixian calendar, which was in turn developed by Jesuit scholars. However, because the Korean calendar is now
44
     * based on the moon's shape seen from Korea, occasionally the calendar diverges from the traditional Chinese
45
     * calendar by one day, even though the underlying rule is the same.
46
     * @link https://en.wikipedia.org/wiki/Korean_calendar
47
     *
48
     * To convert from lunar calendar to Gregorian calendar, lunar observation is necessary.
49
     * There is no perfect formula, and as it moves away from the current date, the error becomes bigger.
50
     * Korea Astronomy and Space Science Institute (KASI) is supporting the converter until 2050.
51
     * For more information, please refer to the paper below.
52
     * 박(2017)총,32(3),407-420.
53
     * @link https://www.kasi.re.kr/kor/research/paper/20170259 - Korea Astronomy and Space Science Institute
54
     */
55
    public const LUNAR_HOLIDAY = [
56
        'seollal' => [
57
            1985 => '1985-2-20', 1986 => '1986-2-9', 1987 => '1987-1-29', 1988 => '1988-2-18', 1989 => '1989-2-6',
58
            1990 => '1990-1-27', 1991 => '1991-2-15', 1992 => '1992-2-4', 1993 => '1993-1-23', 1994 => '1994-2-10',
59
            1995 => '1995-1-31', 1996 => '1996-2-19', 1997 => '1997-2-8', 1998 => '1998-1-28', 1999 => '1999-2-16',
60
            2000 => '2000-2-5', 2001 => '2001-1-24', 2002 => '2002-2-12', 2003 => '2003-2-1', 2004 => '2004-1-22',
61
            2005 => '2005-2-9', 2006 => '2006-1-29', 2007 => '2007-2-18', 2008 => '2008-2-7', 2009 => '2009-1-26',
62
            2010 => '2010-2-14', 2011 => '2011-2-3', 2012 => '2012-1-23', 2013 => '2013-2-10', 2014 => '2014-1-31',
63
            2015 => '2015-2-19', 2016 => '2016-2-8', 2017 => '2017-1-28', 2018 => '2018-2-16', 2019 => '2019-2-5',
64
            2020 => '2020-1-25', 2021 => '2021-2-12', 2022 => '2022-2-1', 2023 => '2023-1-22', 2024 => '2024-2-10',
65
            2025 => '2025-1-29', 2026 => '2026-2-17', 2027 => '2027-2-7', 2028 => '2028-1-27', 2029 => '2029-2-13',
66
            2030 => '2030-2-3', 2031 => '2031-1-23', 2032 => '2032-2-11', 2033 => '2033-1-31', 2034 => '2034-2-19',
67
            2035 => '2035-2-8', 2036 => '2036-1-28', 2037 => '2037-2-15', 2038 => '2038-2-4', 2039 => '2037-1-24',
68
            2040 => '2040-2-12', 2041 => '2041-2-1', 2042 => '2042-1-22', 2043 => '2043-2-10', 2044 => '2044-1-30',
69
            2045 => '2045-2-17', 2046 => '2046-2-6', 2047 => '2047-1-26', 2048 => '2048-2-14', 2049 => '2049-2-2',
70
            2050 => '2050-1-23',
71
        ],
72
        'buddhasBirthday' => [
73
            1975 => '1975-5-18', 1976 => '1976-5-6', 1977 => '1977-5-25', 1978 => '1978-5-14', 1979 => '1979-5-3',
74
            1980 => '1980-5-21', 1981 => '1981-5-11', 1982 => '1982-5-1', 1983 => '1983-5-20', 1984 => '1984-5-8',
75
            1985 => '1985-5-27', 1986 => '1986-5-16', 1987 => '1987-5-5', 1988 => '1988-5-23', 1989 => '1989-5-12',
76
            1990 => '1990-5-2', 1991 => '1991-5-21', 1992 => '1992-5-10', 1993 => '1993-5-28', 1994 => '1994-5-18',
77
            1995 => '1995-5-7', 1996 => '1996-5-24', 1997 => '1997-5-14', 1998 => '1998-5-3', 1999 => '1999-5-22',
78
            2000 => '2000-5-11', 2001 => '2001-4-30', 2002 => '2002-5-19', 2003 => '2003-5-8', 2004 => '2004-5-26',
79
            2005 => '2005-5-15', 2006 => '2006-5-5', 2007 => '2007-5-24', 2008 => '2008-5-12', 2009 => '2009-5-2',
80
            2010 => '2010-5-21', 2011 => '2011-5-10', 2012 => '2012-5-28', 2013 => '2013-5-17', 2014 => '2014-5-6',
81
            2015 => '2015-5-25', 2016 => '2016-5-14', 2017 => '2017-5-3', 2018 => '2018-5-22', 2019 => '2019-5-12',
82
            2020 => '2020-4-30', 2021 => '2021-5-19', 2022 => '2022-5-8', 2023 => '2023-5-27', 2024 => '2024-5-15',
83
            2025 => '2025-5-5', 2026 => '2026-5-24', 2027 => '2027-5-13', 2028 => '2028-5-2', 2029 => '2029-5-20',
84
            2030 => '2030-5-9', 2031 => '2031-5-28', 2032 => '2032-5-16', 2033 => '2033-5-6', 2034 => '2034-5-25',
85
            2035 => '2035-5-15', 2036 => '2036-5-3', 2037 => '2037-5-22', 2038 => '2038-5-11', 2039 => '2039-4-30',
86
            2040 => '2040-5-18', 2041 => '2041-5-7', 2042 => '2042-5-26', 2043 => '2043-5-16', 2044 => '2044-5-5',
87
            2045 => '2045-5-24', 2046 => '2046-5-13', 2047 => '2047-5-2', 2048 => '2048-5-20', 2049 => '2049-5-9',
88
            2050 => '2050-5-28',
89
        ],
90
        'chuseok' => [
91
            1949 => '1949-10-6', 1950 => '1950-9-26', 1951 => '1951-9-15', 1952 => '1952-10-3', 1953 => '1953-9-22',
92
            1954 => '1954-9-11', 1955 => '1955-9-30', 1956 => '1956-9-19', 1957 => '1957-9-8', 1958 => '1958-9-27',
93
            1959 => '1959-9-17', 1960 => '1960-10-5', 1961 => '1961-9-24', 1962 => '1962-9-13', 1963 => '1963-10-2',
94
            1964 => '1964-9-20', 1965 => '1965-9-10', 1966 => '1966-9-29', 1967 => '1967-9-18', 1968 => '1968-10-6',
95
            1969 => '1969-9-26', 1970 => '1970-9-15', 1971 => '1971-10-3', 1972 => '1972-9-22', 1973 => '1973-9-11',
96
            1974 => '1974-9-30', 1975 => '1975-9-20', 1976 => '1976-9-8', 1977 => '1977-9-27', 1978 => '1978-9-17',
97
            1979 => '1979-10-5', 1980 => '1980-9-23', 1981 => '1981-9-12', 1982 => '1982-10-1', 1983 => '1983-9-21',
98
            1984 => '1984-9-10', 1985 => '1985-9-29', 1986 => '1986-9-18', 1987 => '1987-10-7', 1988 => '1988-9-25',
99
            1989 => '1989-9-14', 1990 => '1990-10-3', 1991 => '1991-9-22', 1992 => '1992-9-11', 1993 => '1993-9-30',
100
            1994 => '1994-9-20', 1995 => '1950-9-9', 1996 => '1996-9-27', 1997 => '1997-9-16', 1998 => '1998-10-5',
101
            1999 => '1999-9-24', 2000 => '2000-9-12', 2001 => '2001-10-1', 2002 => '2002-9-21', 2003 => '2003-9-11',
102
            2004 => '2004-9-28', 2005 => '2005-9-18', 2006 => '2006-10-6', 2007 => '2007-9-25', 2008 => '2008-9-14',
103
            2009 => '2009-10-3', 2010 => '2010-9-22', 2011 => '2011-9-12', 2012 => '2012-9-30', 2013 => '2013-9-19',
104
            2014 => '2014-9-8', 2015 => '2015-9-27', 2016 => '2016-9-15', 2017 => '2017-10-4', 2018 => '2018-9-24',
105
            2019 => '2019-9-13', 2020 => '2020-10-1', 2021 => '2021-9-21', 2022 => '2022-9-10', 2023 => '2023-9-29',
106
            2024 => '2024-9-17', 2025 => '2025-10-6', 2026 => '2026-9-25', 2027 => '2027-9-15', 2028 => '2028-10-3',
107
            2029 => '2029-9-22', 2030 => '2030-9-12', 2031 => '2031-10-1', 2032 => '2032-9-19', 2033 => '2033-9-8',
108
            2034 => '2034-9-27', 2035 => '2035-9-16', 2036 => '2036-10-4', 2037 => '2037-9-24', 2038 => '2038-9-13',
109
            2039 => '2039-10-2', 2040 => '2040-9-21', 2041 => '2041-9-10', 2042 => '2042-9-28', 2043 => '2043-9-17',
110
            2044 => '2044-10-5', 2045 => '2045-9-25', 2046 => '2046-9-15', 2047 => '2047-10-4', 2048 => '2048-9-22',
111
            2049 => '2049-9-11', 2050 => '2050-9-30',
112
        ],
113
    ];
114
115
    /**
116
     * Initialize holidays for South Korea.
117
     *
118
     * @throws InvalidDateException
119
     * @throws \InvalidArgumentException
120
     * @throws UnknownLocaleException
121
     * @throws \Exception
122
     */
123
    public function initialize(): void
124
    {
125
        $this->timezone = 'Asia/Seoul';
126
127
        // Add common holidays
128
        $this->calculateNewYearsDay();
129
        if ($this->year >= 1949) {
130
            $this->addHoliday($this->christmasDay($this->year, $this->timezone, $this->locale));
131
        }
132
133
        // Calculate lunar holidays
134
        $this->calculateSeollal();
135
        $this->calculateBuddhasBirthday();
136
        $this->calculateChuseok();
137
138
        // Calculate other holidays
139
        $this->calculateIndependenceMovementDay();
140
        $this->calculateArborDay();
141
        $this->calculateChildrensDay();
142
        $this->calculateMemorialDay();
143
        $this->calculateConstitutionDay();
144
        $this->calculateLiberationDay();
145
        $this->calculateArmedForcesDay();
146
        $this->calculateNationalFoundationDay();
147
        $this->calculateHangulDay();
148
        $this->calculateSubstituteHolidays();
149
    }
150
151
    /**
152
     * New Year's Day. New Year's Day is held on January 1st and established since 1950.
153
     * From the enactment of the First Law to 1998, there was a two or three-day break in the New Year.
154
     *
155
     * @link https://en.wikipedia.org/wiki/New_Year%27s_Day#East_Asian
156
     *
157
     * @throws \Exception
158
     */
159
    public function calculateNewYearsDay(): void
160
    {
161
        if ($this->year >= 1950) {
162
            $this->addHoliday($this->newYearsDay($this->year, $this->timezone, $this->locale));
163
            if ($this->year <= 1998) {
164
                $this->addHoliday(new Holiday(
165
                    'dayAfterNewYearsDay',
166
                    [],
167
                    new DateTime("$this->year-1-2", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
168
                    $this->locale
169
                ));
170
            }
171
            if ($this->year <= 1990) {
172
                $this->addHoliday(new Holiday(
173
                    'twoDaysLaterNewYearsDay',
174
                    ['en' => 'Two Days Later New Year’s Day', 'ko' => '새해 연휴'],
175
                    new DateTime("$this->year-1-3", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
176
                    $this->locale
177
                ));
178
            }
179
        }
180
    }
181
182
    /**
183
     * Seollal (Korean New Year's Day).
184
     * Seollal is held on the 1st day of the 1st lunar month and was established from 1985.
185
     *
186
     * @link https://en.wikipedia.org/wiki/Korean_New_Year
187
     *
188
     * @throws \Exception
189
     */
190
    public function calculateSeollal(): void
191
    {
192
        if ($this->year >= 1985 && isset(self::LUNAR_HOLIDAY['seollal'][$this->year])) {
193
            $seollal = new DateTime(self::LUNAR_HOLIDAY['seollal'][$this->year], DateTimeZoneFactory::getDateTimeZone($this->timezone));
194
            $this->addHoliday(new Holiday(
195
                'seollal',
196
                ['en' => 'Seollal', 'ko' => '설날'],
197
                $seollal,
198
                $this->locale
199
            ));
200
            if ($this->year > 1989) {
201
                $dayBeforeSeollal = clone $seollal;
202
                $dayBeforeSeollal->sub(new DateInterval('P1D'));
203
                $this->addHoliday(new Holiday(
204
                    'dayBeforeSeollal',
205
                    ['en' => 'Day before Seollal', 'ko' => '설날 연휴'],
206
                    $dayBeforeSeollal,
207
                    $this->locale
208
                ));
209
                $dayAfterSeollal = clone $seollal;
210
                $dayAfterSeollal->add(new DateInterval('P1D'));
211
                $this->addHoliday(new Holiday(
212
                    'dayAfterSeollal',
213
                    ['en' => 'Day after Seollal', 'ko' => '설날 연휴'],
214
                    $dayAfterSeollal,
215
                    $this->locale
216
                ));
217
            }
218
        }
219
    }
220
221
    /**
222
     * Buddha's Birthday is held on the 8th day of the 4th lunar month and was established since 1975.
223
     *
224
     * @link https://en.wikipedia.org/wiki/Buddha%27s_Birthday
225
     *
226
     * @throws \Exception
227
     */
228
    public function calculateBuddhasBirthday(): void
229
    {
230
        if ($this->year >= 1975 && isset(self::LUNAR_HOLIDAY['buddhasBirthday'][$this->year])) {
231
            $this->addHoliday(new Holiday(
232
                'buddhasBirthday',
233
                ['en' => 'Buddha’s Birthday', 'ko' => '부처님오신날'],
234
                new DateTime(self::LUNAR_HOLIDAY['buddhasBirthday'][$this->year], DateTimeZoneFactory::getDateTimeZone($this->timezone)),
235
                $this->locale
236
            ));
237
        }
238
    }
239
240
    /**
241
     * Chuseok (Korean Thanksgiving Day).
242
     *
243
     * Chuseok, one of the biggest holidays in Korea, is a major harvest festival and a three-day holiday celebrated on
244
     * the 15th day of the 8th month of the lunar calendar on the full moon.
245
     *
246
     * @link https://en.wikipedia.org/wiki/Chuseok
247
     *
248
     * @throws \Exception
249
     */
250
    public function calculateChuseok(): void
251
    {
252
        if ($this->year >= 1949 && isset(self::LUNAR_HOLIDAY['chuseok'][$this->year])) {
253
            // Chuseok
254
            $chuseok = new Holiday(
255
                'chuseok',
256
                ['en' => 'Chuseok', 'ko' => '추석'],
257
                new DateTime(self::LUNAR_HOLIDAY['chuseok'][$this->year], DateTimeZoneFactory::getDateTimeZone($this->timezone)),
258
                $this->locale
259
            );
260
            $this->addHoliday($chuseok);
261
262
            // Day after Chuseok
263
            if ($this->year >= 1986) {
264
                $this->addHoliday(new Holiday(
265
                    'dayAfterChuseok',
266
                    ['en' => 'Day after Chuseok', 'ko' => '추석 연휴'],
267
                    (clone $chuseok)->add(new DateInterval('P1D')),
268
                    $this->locale
269
                ));
270
            }
271
272
            // Day before Chuseok
273
            if ($this->year >= 1989) {
274
                $this->addHoliday(new Holiday(
275
                    'dayBeforeChuseok',
276
                    ['en' => 'Day before Chuseok', 'ko' => '추석 연휴'],
277
                    (clone $chuseok)->sub(new DateInterval('P1D')),
278
                    $this->locale
279
                ));
280
            }
281
        }
282
    }
283
284
    /**
285
     * Independence Movement Day. Independence Movement Day is held on March 1st and was established from 1949.
286
     *
287
     * @link https://en.wikipedia.org/wiki/Independence_Movement_Day
288
     *
289
     * @throws \Exception
290
     */
291
    public function calculateIndependenceMovementDay(): void
292
    {
293
        if ($this->year >= 1949) {
294
            $this->addHoliday(new Holiday(
295
                'independenceMovementDay',
296
                ['en' => 'Independence Movement Day', 'ko' => '삼일절'],
297
                new DateTime("$this->year-3-1", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
298
                $this->locale
299
            ));
300
        }
301
    }
302
303
    /**
304
     * Sikmogil (Arbor Day). Sikmogil is held on May 5th and established since 1949.
305
     *
306
     * @link https://en.wikipedia.org/wiki/Sikmogil
307
     *
308
     * @throws \Exception
309
     */
310
    public function calculateArborDay(): void
311
    {
312
        if (($this->year >= 1949 && $this->year < 1960) || ($this->year > 1960 && $this->year < 2006)) {
313
            $this->addHoliday(new Holiday(
314
                'arborDay',
315
                ['en' => 'Arbor Day', 'ko' => '식목일'],
316
                new DateTime("$this->year-4-5", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
317
                $this->locale
318
            ));
319
        }
320
    }
321
322
    /**
323
     * Children's Day. Children's Day is held on May 5th and established since 1970.
324
     *
325
     * @link https://en.wikipedia.org/wiki/Children%27s_Day#South_Korea
326
     *
327
     * @throws \Exception
328
     */
329
    public function calculateChildrensDay(): void
330
    {
331
        if ($this->year >= 1970) {
332
            $this->addHoliday(new Holiday(
333
                'childrensDay',
334
                ['en' => 'Children’s Day', 'ko' => '어린이날'],
335
                new DateTime("$this->year-5-5", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
336
                $this->locale
337
            ));
338
        }
339
    }
340
341
    /**
342
     * Memorial Day. Memorial Day is held on June 6th and established since 1956.
343
     *
344
     * @link https://en.wikipedia.org/wiki/Memorial_Day_(South_Korea)
345
     *
346
     * @throws \Exception
347
     */
348
    public function calculateMemorialDay(): void
349
    {
350
        if ($this->year >= 1966) {
351
            $this->addHoliday(new Holiday(
352
                'memorialDay',
353
                ['en' => 'Memorial Day', 'ko' => '현충일'],
354
                new DateTime("$this->year-6-6", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
355
                $this->locale
356
            ));
357
        }
358
    }
359
360
    /**
361
     * Constitution Day.
362
     *
363
     * Constitution Day is held on July 17th and established since 1949.
364
     * Officially, it is a strict national holiday, but government offices and banks work normally after 2008.
365
     *
366
     * @link https://en.wikipedia.org/wiki/Constitution_Day_(South_Korea)
367
     *
368
     * @throws \Exception
369
     */
370
    public function calculateConstitutionDay(): void
371
    {
372
        if ($this->year >= 1949 && $this->year < 2008) {
373
            $this->addHoliday(new Holiday(
374
                'constitutionDay',
375
                ['en' => 'Constitution Day', 'ko' => '제헌절'],
376
                new DateTime("$this->year-7-17", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
377
                $this->locale
378
            ));
379
        }
380
    }
381
382
    /**
383
     * Liberation Day. Liberation Day is held on August 15th and established since 1949.
384
     *
385
     * @link https://en.wikipedia.org/wiki/National_Liberation_Day_of_Korea
386
     *
387
     * @throws \Exception
388
     */
389
    public function calculateLiberationDay(): void
390
    {
391
        if ($this->year >= 1949) {
392
            $this->addHoliday(new Holiday(
393
                'liberationDay',
394
                ['en' => 'Liberation Day', 'ko' => '광복절'],
395
                new DateTime("$this->year-8-15", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
396
                $this->locale
397
            ));
398
        }
399
    }
400
401
    /**
402
     * Armed Forces Day. Armed Forces Day is held on October 1st and established since 1956.
403
     *
404
     * @link https://en.wikipedia.org/wiki/Armed_Forces_Day_(South_Korea)
405
     *
406
     * @throws \Exception
407
     */
408
    public function calculateArmedForcesDay(): void
409
    {
410
        if ($this->year >= 1956 && $this->year <= 1990) {
411
            $this->addHoliday(new Holiday(
412
                'armedForcesDay',
413
                ['en' => 'Armed Forces Day', 'ko' => '국군의 날'],
414
                new DateTime("$this->year-10-1", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
415
                $this->locale
416
            ));
417
        }
418
    }
419
420
    /**
421
     * Gaecheonjeol (National Foundation Day). Gaecheonjeol is held on October 3rd and established since 1949.
422
     *
423
     * @link https://en.wikipedia.org/wiki/Gaecheonjeol
424
     *
425
     * @throws \Exception
426
     */
427
    public function calculateNationalFoundationDay(): void
428
    {
429
        if ($this->year >= 1949) {
430
            $this->addHoliday(new Holiday(
431
                'nationalFoundationDay',
432
                ['en' => 'National Foundation Day', 'ko' => '개천절'],
433
                new DateTime("$this->year-10-3", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
434
                $this->locale
435
            ));
436
        }
437
    }
438
439
    /**
440
     * Hangul Day. Hangul Day is held on October 9th and established since 1949.
441
     *
442
     * @link https://en.wikipedia.org/wiki/Hangul_Day
443
     *
444
     * @throws \Exception
445
     */
446
    public function calculateHangulDay(): void
447
    {
448
        if (($this->year >= 1949 && $this->year <= 1990) || $this->year > 2012) {
449
            $this->addHoliday(new Holiday(
450
                'hangulDay',
451
                ['en' => 'Hangul Day', 'ko' => '한글날'],
452
                new DateTime("$this->year-10-9", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
453
                $this->locale
454
            ));
455
        }
456
    }
457
458
    /**
459
     * Substitute Holidays.
460
     * Related statutes: Article 3 Alternative Statutory Holidays of the Regulations on Holidays of Government Offices
461
     *
462
     * Since 2014, it has been applied only on Seollal, Chuseok and Children's Day.
463
     * Due to the lunar calendar, public holidays can overlap even if it's not a Sunday.
464
     * When public holidays fall on each other, the first non-public holiday after the holiday becomes a public holiday.
465
     * As an exception, Children's Day also applies on Saturday.
466
     *
467
     * @throws \Exception
468
     */
469
    public function calculateSubstituteHolidays(): void
470
    {
471
        if ($this->year <= 2013) {
472
            return;
473
        }
474
475
        // Initialize holidays variable
476
        $holidays = $this->getHolidays();
477
        $acceptedHolidays = [
478
            'dayBeforeSeollal', 'seollal', 'dayAfterSeollal',
479
            'dayBeforeChuseok', 'chuseok', 'dayAfterChuseok',
480
            'childrensDay',
481
        ];
482
483
        // Loop through all holidays
484
        foreach ($holidays as $key => $holiday) {
485
            // Get list of holiday dates except this
486
            $holidayDates = \array_map(static function ($holiday) use ($key) {
487
                return $holiday->getKey() === $key ? false : (string) $holiday;
488
            }, $holidays);
489
490
            // Only process accepted holidays and conditions
491
            if (\in_array($key, $acceptedHolidays, true)
492
                && (
493
                    0 === (int) $holiday->format('w')
494
                    || \in_array($holiday, $holidayDates, false)
495
                    || (6 === (int) $holiday->format('w') && 'childrensDay' === $key)
496
                )
497
            ) {
498
                $date = clone $holiday;
499
500
                // Find next week day (not being another holiday)
501
                while (0 === (int) $date->format('w')
502
                    || (6 === (int) $date->format('w') && 'childrensDay' === $key)
503
                    || \in_array($date, $holidayDates, false)) {
504
                    $date->add(new DateInterval('P1D'));
505
                    continue;
506
                }
507
508
                // Add a new holiday that is substituting the original holiday
509
                $substitute = new SubstituteHoliday(
510
                    $holiday,
511
                    [],
512
                    $date,
513
                    $this->locale
514
                );
515
516
                // Add a new holiday that is substituting the original holiday
517
                $this->addHoliday($substitute);
518
519
                // Add substitute holiday to the list
520
                $holidays[] = $substitute;
521
            }
522
        }
523
    }
524
}
525