diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a5ba753a..ceafc3eb9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,10 +12,23 @@ changes. ### Added +- Recently, the South Korean government announced a bill to apply alternative public holidays to Buddha's Day + and Christmas Day, which we have reflected in our South Korea provider. + [\#314](https://github.com/azuyalabs/yasumi/pull/314) ([barami](https://github.com/barami)) + ### Changed +- Updated links to related documentation in the SouthKorea provider's note and added links to conversion utilities. + [\#314](https://github.com/azuyalabs/yasumi/pull/314) ([barami](https://github.com/barami)) +- Refactored the complexity of the SouthKorea provider to make it easier to understand in case of future changes. + [\#314](https://github.com/azuyalabs/yasumi/pull/314) ([barami](https://github.com/barami)) + ### Fixed +- Fixed a bug in the South Korea provider where some of the past dates for Buddha's Day, Chuseok, Armed Forces Day + and United Nations Day were incorrect during holidays, and modified the unit tests accordingly. + [\#314](https://github.com/azuyalabs/yasumi/pull/314) ([barami](https://github.com/barami)) + ### Removed ## [2.6.0] - 2023-04-27 diff --git a/src/Yasumi/Provider/SouthKorea.php b/src/Yasumi/Provider/SouthKorea.php index dcb5952ea..50547a994 100644 --- a/src/Yasumi/Provider/SouthKorea.php +++ b/src/Yasumi/Provider/SouthKorea.php @@ -51,7 +51,8 @@ class SouthKorea extends AbstractProvider * Korea Astronomy and Space Science Institute (KASI) is supporting the converter until 2050. * For more information, please refer to the paper below. * 박(2017)총,32(3),407-420. - * @see https://www.kasi.re.kr/kor/research/paper/20170259 - Korea Astronomy and Space Science Institute + * @see https://koreascience.kr/article/JAKO201706163145174.pdf - Korea Astronomy and Space Science Institute + * @see https://astro.kasi.re.kr/life/pageView/8 - web utility for conversion and retrieve */ public const LUNAR_HOLIDAY = [ 'seollal' => [ @@ -76,7 +77,7 @@ class SouthKorea extends AbstractProvider 1985 => '1985-5-27', 1986 => '1986-5-16', 1987 => '1987-5-5', 1988 => '1988-5-23', 1989 => '1989-5-12', 1990 => '1990-5-2', 1991 => '1991-5-21', 1992 => '1992-5-10', 1993 => '1993-5-28', 1994 => '1994-5-18', 1995 => '1995-5-7', 1996 => '1996-5-24', 1997 => '1997-5-14', 1998 => '1998-5-3', 1999 => '1999-5-22', - 2000 => '2000-5-11', 2001 => '2001-4-30', 2002 => '2002-5-19', 2003 => '2003-5-8', 2004 => '2004-5-26', + 2000 => '2000-5-11', 2001 => '2001-5-1', 2002 => '2002-5-19', 2003 => '2003-5-8', 2004 => '2004-5-26', 2005 => '2005-5-15', 2006 => '2006-5-5', 2007 => '2007-5-24', 2008 => '2008-5-12', 2009 => '2009-5-2', 2010 => '2010-5-21', 2011 => '2011-5-10', 2012 => '2012-5-28', 2013 => '2013-5-17', 2014 => '2014-5-6', 2015 => '2015-5-25', 2016 => '2016-5-14', 2017 => '2017-5-3', 2018 => '2018-5-22', 2019 => '2019-5-12', @@ -98,7 +99,7 @@ class SouthKorea extends AbstractProvider 1979 => '1979-10-5', 1980 => '1980-9-23', 1981 => '1981-9-12', 1982 => '1982-10-1', 1983 => '1983-9-21', 1984 => '1984-9-10', 1985 => '1985-9-29', 1986 => '1986-9-18', 1987 => '1987-10-7', 1988 => '1988-9-25', 1989 => '1989-9-14', 1990 => '1990-10-3', 1991 => '1991-9-22', 1992 => '1992-9-11', 1993 => '1993-9-30', - 1994 => '1994-9-20', 1995 => '1950-9-9', 1996 => '1996-9-27', 1997 => '1997-9-16', 1998 => '1998-10-5', + 1994 => '1994-9-20', 1995 => '1995-9-9', 1996 => '1996-9-27', 1997 => '1997-9-16', 1998 => '1998-10-5', 1999 => '1999-9-24', 2000 => '2000-9-12', 2001 => '2001-10-1', 2002 => '2002-9-21', 2003 => '2003-9-11', 2004 => '2004-9-28', 2005 => '2005-9-18', 2006 => '2006-10-6', 2007 => '2007-9-25', 2008 => '2008-9-14', 2009 => '2009-10-3', 2010 => '2010-9-22', 2011 => '2011-9-12', 2012 => '2012-9-30', 2013 => '2013-9-19', @@ -113,6 +114,90 @@ class SouthKorea extends AbstractProvider ], ]; + /** + * Collection of all historically recognized holidays in South Korea. + * + * Aggregated collection of all historically recognized holidays of South Korea After the government was established. + * This collection also includes items that are now obsolete and excluded from holidays. + */ + public const HOLIDAY_NAMES = [ + 'newYearsDay' => [], + 'dayAfterNewYearsDay' => [], + 'twoDaysLaterNewYearsDay' => [ + 'en' => 'Two Days Later New Year’s Day', + 'ko' => '새해 연휴', + ], + 'seollal' => [ + 'en' => 'Seollal', + 'ko' => '설날', + ], + 'dayBeforeSeollal' => [ + 'en' => 'Day before Seollal', + 'ko' => '설날 연휴', + ], + 'dayAfterSeollal' => [ + 'en' => 'Day after Seollal', + 'ko' => '설날 연휴', + ], + 'independenceMovementDay' => [ + 'en' => 'Independence Movement Day', + 'ko' => '삼일절', + ], + 'arborDay' => [ + 'en' => 'Arbor Day', + 'ko' => '식목일', + ], + 'buddhasBirthday' => [ + 'en' => 'Buddha’s Birthday', + 'ko' => '부처님오신날', + ], + 'childrensDay' => [ + 'en' => 'Children’s Day', + 'ko' => '어린이날', + ], + 'memorialDay' => [ + 'en' => 'Memorial Day', + 'ko' => '현충일', + ], + 'constitutionDay' => [ + 'en' => 'Constitution Day', + 'ko' => '제헌절', + ], + 'liberationDay' => [ + 'en' => 'Liberation Day', + 'ko' => '광복절', + ], + 'chuseok' => [ + 'en' => 'Chuseok', + 'ko' => '추석', + ], + 'dayBeforeChuseok' => [ + 'en' => 'Day before Chuseok', + 'ko' => '추석 연휴', + ], + 'dayAfterChuseok' => [ + 'en' => 'Day after Chuseok', + 'ko' => '추석 연휴', + ], + 'armedForcesDay' => [ + 'en' => 'Armed Forces Day', + 'ko' => '국군의 날', + ], + 'nationalFoundationDay' => [ + 'en' => 'National Foundation Day', + 'ko' => '개천절', + ], + 'hangulDay' => [ + 'en' => 'Hangul Day', + 'ko' => '한글날', + ], + 'unitedNationsDay' => [ + 'en' => 'United Nations Day', + 'ko' => '유엔의 날', + ], + 'christmasDay' => [], + ]; + /** * Initialize holidays for South Korea. * @@ -124,28 +209,25 @@ public function initialize(): void { $this->timezone = 'Asia/Seoul'; - // Add common holidays - $this->calculateNewYearsDay(); - if ($this->year >= 1949) { - $this->addHoliday($this->christmasDay($this->year, $this->timezone, $this->locale)); + // Fast-fail when before 1949 + if ($this->year < 1949) { + return; + } + + if ($this->year < 2013) { + // Holidays in used from 1949 until 2012 + $officialHolidays = $this->calculateBefore2013($this->year); + } else { + // Holidays in use from 2013 + $officialHolidays = $this->calculateCurrent($this->year); + } + + foreach ($officialHolidays as $holiday) { + $this->addHoliday($this->{$holiday}($this->year, $this->timezone, $this->locale)); } - // Calculate lunar holidays - $this->calculateSeollal(); - $this->calculateBuddhasBirthday(); - $this->calculateChuseok(); - - // Calculate other holidays - $this->calculateIndependenceMovementDay(); - $this->calculateArborDay(); - $this->calculateChildrensDay(); - $this->calculateMemorialDay(); - $this->calculateConstitutionDay(); - $this->calculateLiberationDay(); - $this->calculateArmedForcesDay(); - $this->calculateNationalFoundationDay(); - $this->calculateHangulDay(); - $this->calculateSubstituteHolidays(); + // Substitute Holidays + $this->calculateSubstituteHolidays($this->year); } public function getSources(): array @@ -157,333 +239,600 @@ public function getSources(): array ]; } - /** - * New Year's Day. New Year's Day is held on January 1st and established since 1950. - * From the enactment of the First Law to 1998, there was a two or three-day break in the New Year. - * - * @see https://en.wikipedia.org/wiki/New_Year%27s_Day#East_Asian - * - * @throws \Exception - */ - private function calculateNewYearsDay(): void + public function addHoliday(?Holiday $holiday): void { - if ($this->year >= 1950) { - $this->addHoliday($this->newYearsDay($this->year, $this->timezone, $this->locale)); - if ($this->year <= 1998) { - $this->addHoliday(new Holiday( - 'dayAfterNewYearsDay', - [], - new \DateTime("$this->year-1-2", DateTimeZoneFactory::getDateTimeZone($this->timezone)), - $this->locale - )); - } - if ($this->year <= 1990) { - $this->addHoliday(new Holiday( - 'twoDaysLaterNewYearsDay', - ['en' => 'Two Days Later New Year’s Day', 'ko' => '새해 연휴'], - new \DateTime("$this->year-1-3", DateTimeZoneFactory::getDateTimeZone($this->timezone)), - $this->locale - )); - } + if (isset($holiday)) { + parent::addHoliday($holiday); } } + /** + * The day after New Year's Day (January 2) + * This day was established in 1949 and then removed as a public holiday in 1999. + */ + protected function dayAfterNewYearsDay( + int $year, + string $timezone, + string $locale, + string $type = Holiday::TYPE_OFFICIAL + ): Holiday { + return new Holiday( + 'dayAfterNewYearsDay', + $this->getTranslations('dayAfterNewYearsDay', $year), + new \DateTime("$year-1-2", DateTimeZoneFactory::getDateTimeZone($timezone)), + $locale, + $type + ); + } + + /** + * Two days after the New Year's (January 3) + * This day was established in 1949 and then removed as a public holiday in 1990. + */ + protected function twoDaysLaterNewYearsDay( + int $year, + string $timezone, + string $locale, + string $type = Holiday::TYPE_OFFICIAL + ): Holiday { + return new Holiday( + 'twoDaysLaterNewYearsDay', + $this->getTranslations('twoDaysLaterNewYearsDay', $year), + new \DateTime("$year-1-3", DateTimeZoneFactory::getDateTimeZone($timezone)), + $locale, + $type + ); + } + /** * Seollal (Korean New Year's Day). * Seollal is held on the 1st day of the 1st lunar month and was established from 1985. * - * @see https://en.wikipedia.org/wiki/Korean_New_Year + * Seollal was celebrated with only one day off when it was established in 1985, and then changed to a three-day holiday in 1989. * - * @throws \Exception + * @see https://en.wikipedia.org/wiki/Korean_New_Year */ - private function calculateSeollal(): void - { - if ($this->year >= 1985 && isset(self::LUNAR_HOLIDAY['seollal'][$this->year])) { - $seollal = new \DateTime(self::LUNAR_HOLIDAY['seollal'][$this->year], DateTimeZoneFactory::getDateTimeZone($this->timezone)); - $this->addHoliday(new Holiday( - 'seollal', - ['en' => 'Seollal', 'ko' => '설날'], - $seollal, - $this->locale - )); - if ($this->year > 1989) { - $dayBeforeSeollal = clone $seollal; - $dayBeforeSeollal->sub(new \DateInterval('P1D')); - $this->addHoliday(new Holiday( - 'dayBeforeSeollal', - ['en' => 'Day before Seollal', 'ko' => '설날 연휴'], - $dayBeforeSeollal, - $this->locale - )); - $dayAfterSeollal = clone $seollal; - $dayAfterSeollal->add(new \DateInterval('P1D')); - $this->addHoliday(new Holiday( - 'dayAfterSeollal', - ['en' => 'Day after Seollal', 'ko' => '설날 연휴'], - $dayAfterSeollal, - $this->locale - )); - } + protected function seollal( + int $year, + string $timezone, + string $locale, + string $type = Holiday::TYPE_OFFICIAL + ): ?Holiday { + if (! isset(self::LUNAR_HOLIDAY['seollal'][$year])) { + return null; } + + $seollal = self::LUNAR_HOLIDAY['seollal'][$year]; + + return new Holiday( + 'seollal', + $this->getTranslations('seollal', $year), + new \DateTime($seollal, DateTimeZoneFactory::getDateTimeZone($timezone)), + $locale, + $type + ); } /** - * Buddha's Birthday is held on the 8th day of the 4th lunar month and was established since 1975. + * The day before Seollal (Korean New Year's Day). + * Seollal is held on the 1st day of the 1st lunar month and was established from 1985. * - * @see https://en.wikipedia.org/wiki/Buddha%27s_Birthday + * Seollal was celebrated with only one day off when it was established in 1985, and then changed to a three-day holiday in 1989. * - * @throws \Exception + * @see https://en.wikipedia.org/wiki/Korean_New_Year */ - private function calculateBuddhasBirthday(): void - { - if ($this->year < 1975) { - return; + protected function dayBeforeSeollal( + int $year, + string $timezone, + string $locale, + string $type = Holiday::TYPE_OFFICIAL + ): ?Holiday { + if (! isset(self::LUNAR_HOLIDAY['seollal'][$year])) { + return null; } - if (! isset(self::LUNAR_HOLIDAY['buddhasBirthday'][$this->year])) { - return; - } + $seollal = self::LUNAR_HOLIDAY['seollal'][$year]; - $this->addHoliday(new Holiday( - 'buddhasBirthday', - ['en' => 'Buddha’s Birthday', 'ko' => '부처님오신날'], - new \DateTime(self::LUNAR_HOLIDAY['buddhasBirthday'][$this->year], DateTimeZoneFactory::getDateTimeZone($this->timezone)), - $this->locale - )); + return new Holiday( + 'dayBeforeSeollal', + $this->getTranslations('dayBeforeSeollal', $year), + new \DateTime("-1 day $seollal", DateTimeZoneFactory::getDateTimeZone($timezone)), + $locale, + $type + ); } /** - * Chuseok (Korean Thanksgiving Day). - * - * Chuseok, one of the biggest holidays in Korea, is a major harvest festival and a three-day holiday celebrated on - * the 15th day of the 8th month of the lunar calendar on the full moon. + * The day after Seollal (Korean New Year's Day). + * Seollal is held on the 1st day of the 1st lunar month and was established from 1985. * - * @see https://en.wikipedia.org/wiki/Chuseok + * Seollal was celebrated with only one day off when it was established in 1985, and then changed to a three-day holiday in 1989. * - * @throws \Exception + * @see https://en.wikipedia.org/wiki/Korean_New_Year */ - private function calculateChuseok(): void - { - if ($this->year >= 1949 && isset(self::LUNAR_HOLIDAY['chuseok'][$this->year])) { - // Chuseok - $chuseok = new Holiday( - 'chuseok', - ['en' => 'Chuseok', 'ko' => '추석'], - new \DateTime(self::LUNAR_HOLIDAY['chuseok'][$this->year], DateTimeZoneFactory::getDateTimeZone($this->timezone)), - $this->locale - ); - $this->addHoliday($chuseok); - - // Day after Chuseok - if ($this->year >= 1986) { - $this->addHoliday(new Holiday( - 'dayAfterChuseok', - ['en' => 'Day after Chuseok', 'ko' => '추석 연휴'], - (clone $chuseok)->add(new \DateInterval('P1D')), - $this->locale - )); - } - - // Day before Chuseok - if ($this->year >= 1989) { - $this->addHoliday(new Holiday( - 'dayBeforeChuseok', - ['en' => 'Day before Chuseok', 'ko' => '추석 연휴'], - (clone $chuseok)->sub(new \DateInterval('P1D')), - $this->locale - )); - } + protected function dayAfterSeollal( + int $year, + string $timezone, + string $locale, + string $type = Holiday::TYPE_OFFICIAL + ): ?Holiday { + if (! isset(self::LUNAR_HOLIDAY['seollal'][$year])) { + return null; } + + $seollal = self::LUNAR_HOLIDAY['seollal'][$year]; + + return new Holiday( + 'dayAfterSeollal', + $this->getTranslations('dayAfterSeollal', $year), + new \DateTime("+1 day $seollal", DateTimeZoneFactory::getDateTimeZone($timezone)), + $locale, + $type + ); } /** - * Independence Movement Day. Independence Movement Day is held on March 1st and was established from 1949. + * Independence Movement Day. + * Independence Movement Day is held on March 1st and was established from 1949. * * @see https://en.wikipedia.org/wiki/Independence_Movement_Day - * - * @throws \Exception */ - private function calculateIndependenceMovementDay(): void - { - if ($this->year >= 1949) { - $this->addHoliday(new Holiday( - 'independenceMovementDay', - ['en' => 'Independence Movement Day', 'ko' => '삼일절'], - new \DateTime("$this->year-3-1", DateTimeZoneFactory::getDateTimeZone($this->timezone)), - $this->locale - )); - } + protected function independenceMovementDay( + int $year, + string $timezone, + string $locale, + string $type = Holiday::TYPE_OFFICIAL + ): Holiday { + return new Holiday( + 'independenceMovementDay', + $this->getTranslations('independenceMovementDay', $year), + new \DateTime("$year-3-1", DateTimeZoneFactory::getDateTimeZone($timezone)), + $locale, + $type + ); } /** - * Sikmogil (Arbor Day). Sikmogil is held on May 5th and established since 1949. + * Sikmogil (Arbor Day). + * Sikmogil is held on April 5th and established since 1949, but was removed as a public holiday in 2006. * * @see https://en.wikipedia.org/wiki/Sikmogil + */ + protected function arborDay( + int $year, + string $timezone, + string $locale, + string $type = Holiday::TYPE_OFFICIAL + ): Holiday { + $datetime = (1960 === $year) ? "$year-3-21" : "$year-4-5"; + + return new Holiday( + 'arborDay', + $this->getTranslations('arborDay', $year), + new \DateTime($datetime, DateTimeZoneFactory::getDateTimeZone($timezone)), + $locale, + $type + ); + } + + /** + * Buddha's Birthday. + * Buddha's Birthday is held on the 8th day of the 4th lunar month and was established since 1975. * - * @throws \Exception + * @see https://en.wikipedia.org/wiki/Buddha%27s_Birthday */ - private function calculateArborDay(): void - { - if (($this->year >= 1949 && $this->year < 1960) || ($this->year > 1960 && $this->year < 2006)) { - $this->addHoliday(new Holiday( - 'arborDay', - ['en' => 'Arbor Day', 'ko' => '식목일'], - new \DateTime("$this->year-4-5", DateTimeZoneFactory::getDateTimeZone($this->timezone)), - $this->locale - )); + protected function buddhasBirthday( + int $year, + string $timezone, + string $locale, + string $type = Holiday::TYPE_OFFICIAL + ): ?Holiday { + if (! isset(self::LUNAR_HOLIDAY['buddhasBirthday'][$year])) { + return null; } + + $buddhasBirthday = self::LUNAR_HOLIDAY['buddhasBirthday'][$year]; + + return new Holiday( + 'buddhasBirthday', + $this->getTranslations('buddhasBirthday', $year), + new \DateTime($buddhasBirthday, DateTimeZoneFactory::getDateTimeZone($timezone)), + $locale, + $type + ); } /** - * Children's Day. Children's Day is held on May 5th and established since 1970. + * Children's Day. + * Children's Day is held on May 5th and established since 1975. * * @see https://en.wikipedia.org/wiki/Children%27s_Day#South_Korea - * - * @throws \Exception */ - private function calculateChildrensDay(): void - { - if ($this->year >= 1970) { - $this->addHoliday(new Holiday( - 'childrensDay', - ['en' => 'Children’s Day', 'ko' => '어린이날'], - new \DateTime("$this->year-5-5", DateTimeZoneFactory::getDateTimeZone($this->timezone)), - $this->locale - )); - } + protected function childrensDay( + int $year, + string $timezone, + string $locale, + string $type = Holiday::TYPE_OFFICIAL + ): Holiday { + return new Holiday( + 'childrensDay', + $this->getTranslations('childrensDay', $year), + new \DateTime("$year-5-5", DateTimeZoneFactory::getDateTimeZone($timezone)), + $locale, + $type + ); } /** - * Memorial Day. Memorial Day is held on June 6th and established since 1956. + * Memorial Day. + * Memorial Day is held on June 6th and established since 1956. * * @see https://en.wikipedia.org/wiki/Memorial_Day_(South_Korea) - * - * @throws \Exception */ - private function calculateMemorialDay(): void - { - if ($this->year >= 1966) { - $this->addHoliday(new Holiday( - 'memorialDay', - ['en' => 'Memorial Day', 'ko' => '현충일'], - new \DateTime("$this->year-6-6", DateTimeZoneFactory::getDateTimeZone($this->timezone)), - $this->locale - )); - } + protected function memorialDay( + int $year, + string $timezone, + string $locale, + string $type = Holiday::TYPE_OFFICIAL + ): Holiday { + return new Holiday( + 'memorialDay', + $this->getTranslations('memorialDay', $year), + new \DateTime("$year-6-6", DateTimeZoneFactory::getDateTimeZone($timezone)), + $locale, + $type + ); } /** * Constitution Day. - * * Constitution Day is held on July 17th and established since 1949. - * Officially, it is a strict national holiday, but government offices and banks work normally after 2008. + * + * It was originally a public holiday recognized by the South Korean government, + * but was removed as a public holiday in 2008 and is now a national day rather than a public holiday. * * @see https://en.wikipedia.org/wiki/Constitution_Day_(South_Korea) + */ + protected function constitutionDay( + int $year, + string $timezone, + string $locale, + string $type = Holiday::TYPE_OFFICIAL + ): Holiday { + return new Holiday( + 'constitutionDay', + $this->getTranslations('constitutionDay', $year), + new \DateTime("$year-7-17", DateTimeZoneFactory::getDateTimeZone($timezone)), + $locale, + $type + ); + } + + /** + * Liberation Day. + * Liberation Day is held on August 15th and established since 1949. * - * @throws \Exception + * @see https://en.wikipedia.org/wiki/National_Liberation_Day_of_Korea */ - private function calculateConstitutionDay(): void - { - if ($this->year < 1949) { - return; - } + protected function liberationDay( + int $year, + string $timezone, + string $locale, + string $type = Holiday::TYPE_OFFICIAL + ): Holiday { + return new Holiday( + 'liberationDay', + $this->getTranslations('liberationDay', $year), + new \DateTime("$year-8-15", DateTimeZoneFactory::getDateTimeZone($timezone)), + $locale, + $type + ); + } - if ($this->year >= 2008) { - return; + /** + * Chuseok (Korean Thanksgiving Day). + * + * Chuseok, one of the biggest holidays in Korea, is a major harvest festival and a three-day holiday celebrated on + * the 15th day of the 8th month of the lunar calendar on the full moon. + * Chuseok was a one-day holiday when it was established in 1945, but was changed to a three-day holiday in 1989. + * + * @see https://en.wikipedia.org/wiki/Chuseok + */ + protected function chuseok( + int $year, + string $timezone, + string $locale, + string $type = Holiday::TYPE_OFFICIAL + ): ?Holiday { + if (! isset(self::LUNAR_HOLIDAY['chuseok'][$year])) { + return null; } - $this->addHoliday(new Holiday( - 'constitutionDay', - ['en' => 'Constitution Day', 'ko' => '제헌절'], - new \DateTime("$this->year-7-17", DateTimeZoneFactory::getDateTimeZone($this->timezone)), - $this->locale - )); + $choseok = self::LUNAR_HOLIDAY['chuseok'][$year]; + + return new Holiday( + 'chuseok', + $this->getTranslations('chuseok', $year), + new \DateTime($choseok, DateTimeZoneFactory::getDateTimeZone($timezone)), + $locale, + $type + ); } /** - * Liberation Day. Liberation Day is held on August 15th and established since 1949. + * The day before Chuseok (Korean Thanksgiving Day). * - * @see https://en.wikipedia.org/wiki/National_Liberation_Day_of_Korea + * Chuseok, one of the biggest holidays in Korea, is a major harvest festival and a three-day holiday celebrated on + * the 15th day of the 8th month of the lunar calendar on the full moon. + * Chuseok was a one-day holiday when it was established in 1945, but was changed to a three-day holiday in 1989. * - * @throws \Exception + * @see https://en.wikipedia.org/wiki/Chuseok */ - private function calculateLiberationDay(): void - { - if ($this->year >= 1949) { - $this->addHoliday(new Holiday( - 'liberationDay', - ['en' => 'Liberation Day', 'ko' => '광복절'], - new \DateTime("$this->year-8-15", DateTimeZoneFactory::getDateTimeZone($this->timezone)), - $this->locale - )); + protected function dayBeforeChuseok( + int $year, + string $timezone, + string $locale, + string $type = Holiday::TYPE_OFFICIAL + ): ?Holiday { + if (! isset(self::LUNAR_HOLIDAY['chuseok'][$year])) { + return null; } + + $choseok = self::LUNAR_HOLIDAY['chuseok'][$year]; + + return new Holiday( + 'dayBeforeChuseok', + $this->getTranslations('dayBeforeChuseok', $year), + new \DateTime("-1 day $choseok", DateTimeZoneFactory::getDateTimeZone($timezone)), + $locale, + $type + ); } /** - * Armed Forces Day. Armed Forces Day is held on October 1st and established since 1956. + * The day after Chuseok (Korean Thanksgiving Day). * - * @see https://en.wikipedia.org/wiki/Armed_Forces_Day_(South_Korea) + * Chuseok, one of the biggest holidays in Korea, is a major harvest festival and a three-day holiday celebrated on + * the 15th day of the 8th month of the lunar calendar on the full moon. + * Chuseok was a one-day holiday when it was established in 1945, but was changed to a three-day holiday in 1989. * - * @throws \Exception + * @see https://en.wikipedia.org/wiki/Chuseok */ - private function calculateArmedForcesDay(): void - { - if ($this->year < 1956) { - return; + protected function dayAfterChuseok( + int $year, + string $timezone, + string $locale, + string $type = Holiday::TYPE_OFFICIAL + ): ?Holiday { + if (! isset(self::LUNAR_HOLIDAY['chuseok'][$year])) { + return null; } - if ($this->year > 1990) { - return; - } + $choseok = self::LUNAR_HOLIDAY['chuseok'][$year]; + + return new Holiday( + 'dayAfterChuseok', + $this->getTranslations('dayAfterChuseok', $year), + new \DateTime("+1 day $choseok", DateTimeZoneFactory::getDateTimeZone($timezone)), + $locale, + $type + ); + } - $this->addHoliday(new Holiday( + /** + * Armed Forces Day. + * Armed Forces Day is held on October 1st and established since 1956. + * + * Armed Forces Day, established in 1956, was made a public holiday in 1976 and then removed again in 1991. + * + * @see unitedNationsDay + * @see https://en.wikipedia.org/wiki/Armed_Forces_Day_(South_Korea) + */ + protected function armedForcesDay( + int $year, + string $timezone, + string $locale, + string $type = Holiday::TYPE_OFFICIAL + ): Holiday { + return new Holiday( 'armedForcesDay', - ['en' => 'Armed Forces Day', 'ko' => '국군의 날'], - new \DateTime("$this->year-10-1", DateTimeZoneFactory::getDateTimeZone($this->timezone)), - $this->locale - )); + $this->getTranslations('armedForcesDay', $year), + new \DateTime("$year-10-1", DateTimeZoneFactory::getDateTimeZone($timezone)), + $locale, + $type + ); } /** - * Gaecheonjeol (National Foundation Day). Gaecheonjeol is held on October 3rd and established since 1949. + * Gaecheonjeol (National Foundation Day). + * Gaecheonjeol is held on October 3rd and established since 1949. * * @see https://en.wikipedia.org/wiki/Gaecheonjeol + */ + protected function nationalFoundationDay( + int $year, + string $timezone, + string $locale, + string $type = Holiday::TYPE_OFFICIAL + ): Holiday { + return new Holiday( + 'nationalFoundationDay', + $this->getTranslations('nationalFoundationDay', $year), + new \DateTime("$year-10-3", DateTimeZoneFactory::getDateTimeZone($timezone)), + $locale, + $type + ); + } + + /** + * Hangul Day. + * Hangul Day is held on October 9th and established since 1949. * - * @throws \Exception + * Hangul Day, established in 1949, was removed as a public holiday in 1991 and included again in 2013. + * + * @see https://en.wikipedia.org/wiki/Hangul_Day + */ + protected function hangulDay( + int $year, + string $timezone, + string $locale, + string $type = Holiday::TYPE_OFFICIAL + ): Holiday { + return new Holiday( + 'hangulDay', + $this->getTranslations('hangulDay', $year), + new \DateTime("$year-10-9", DateTimeZoneFactory::getDateTimeZone($timezone)), + $locale, + $type + ); + } + + /** + * United Nations Day. + * + * On September 18, 1950, the day of the formation of the United Nations, International United Nations Day was established as a public holiday. + * Later, on September 3, 1976, United Nations Day was removed as a public holiday and Armed Forces Day was established as a new public holiday. + * + * @see https://ko.wikipedia.org/wiki/%EC%9C%A0%EC%97%94%EC%9D%98_%EB%82%A0#%EB%8C%80%ED%95%9C%EB%AF%BC%EA%B5%AD */ - private function calculateNationalFoundationDay(): void + protected function unitedNationsDay( + int $year, + string $timezone, + string $locale, + string $type = Holiday::TYPE_OFFICIAL + ): Holiday { + return new Holiday( + 'unitedNationsDay', + $this->getTranslations('unitedNationsDay', $year), + new \DateTime("$year-10-24", DateTimeZoneFactory::getDateTimeZone($timezone)), + $locale, + $type + ); + } + + /** + * Get holiday names for translation. + * + * @return array + */ + protected function getTranslations(string $key, int $year): array { - if ($this->year >= 1949) { - $this->addHoliday(new Holiday( - 'nationalFoundationDay', - ['en' => 'National Foundation Day', 'ko' => '개천절'], - new \DateTime("$this->year-10-3", DateTimeZoneFactory::getDateTimeZone($this->timezone)), - $this->locale - )); + switch ($key) { + case 'arborDay': + $names = (1960 === $year) + ? ['en' => 'Arbor Day', 'ko' => '사방의 날'] + : self::HOLIDAY_NAMES[$key]; + break; + default: + $names = isset(self::HOLIDAY_NAMES[$key]) ? self::HOLIDAY_NAMES[$key] : []; + break; } + + return $names; } /** - * Hangul Day. Hangul Day is held on October 9th and established since 1949. + * Holidays in used from 1949 until 2012. * - * @see https://en.wikipedia.org/wiki/Hangul_Day - * - * @throws \Exception + * @return array list of holidays */ - private function calculateHangulDay(): void + private function calculateBefore2013(int $year): array { - if (($this->year >= 1949 && $this->year <= 1990) || $this->year > 2012) { - $this->addHoliday(new Holiday( - 'hangulDay', - ['en' => 'Hangul Day', 'ko' => '한글날'], - new \DateTime("$this->year-10-9", DateTimeZoneFactory::getDateTimeZone($this->timezone)), - $this->locale - )); + $officialHolidays = []; + + if ($year >= 1949) { + $officialHolidays[] = 'independenceMovementDay'; + $officialHolidays[] = 'liberationDay'; + $officialHolidays[] = 'nationalFoundationDay'; + $officialHolidays[] = 'newYearsDay'; + $officialHolidays[] = 'chuseok'; + $officialHolidays[] = 'christmasDay'; + + if ($year >= 1950 && $year < 1976) { + $officialHolidays[] = 'unitedNationsDay'; + } + + if ($year >= 1956) { + $officialHolidays[] = 'memorialDay'; + } + + if ($year >= 1975) { + $officialHolidays[] = 'childrensDay'; + $officialHolidays[] = 'buddhasBirthday'; + } + + if ($year >= 1976 && $year <= 1990) { + $officialHolidays[] = 'armedForcesDay'; + } + + if ($year >= 1985) { + $officialHolidays[] = 'seollal'; + } + + if ($year >= 1986) { + $officialHolidays[] = 'dayAfterChuseok'; + } + + if ($year >= 1989) { + $officialHolidays[] = 'dayBeforeChuseok'; + $officialHolidays[] = 'dayBeforeSeollal'; + $officialHolidays[] = 'dayAfterSeollal'; + } + + if ($year <= 1989) { + $officialHolidays[] = 'twoDaysLaterNewYearsDay'; + } + + if ($year <= 1990 || $year > 2012) { + $officialHolidays[] = 'hangulDay'; + } + + if ($year <= 1998) { + $officialHolidays[] = 'dayAfterNewYearsDay'; + } + + if ($year <= 2005) { + $officialHolidays[] = 'arborDay'; + } + + if ($year < 2008) { + $officialHolidays[] = 'constitutionDay'; + } } + + return $officialHolidays; + } + + /** + * Holidays in use since 2013. + * + * @return array list of holidays + */ + private function calculateCurrent(int $year): array + { + $officialHolidays = []; + + $officialHolidays[] = 'newYearsDay'; + $officialHolidays[] = 'dayBeforeSeollal'; + $officialHolidays[] = 'seollal'; + $officialHolidays[] = 'dayAfterSeollal'; + $officialHolidays[] = 'independenceMovementDay'; + $officialHolidays[] = 'buddhasBirthday'; + $officialHolidays[] = 'childrensDay'; + $officialHolidays[] = 'memorialDay'; + $officialHolidays[] = 'liberationDay'; + $officialHolidays[] = 'dayBeforeChuseok'; + $officialHolidays[] = 'chuseok'; + $officialHolidays[] = 'dayAfterChuseok'; + $officialHolidays[] = 'nationalFoundationDay'; + $officialHolidays[] = 'hangulDay'; + $officialHolidays[] = 'christmasDay'; + + return $officialHolidays; } /** - * Substitute Holidays up to 2021. + * Substitute Holidays up to 2022. * Related statutes: Article 3 Alternative Statutory Holidays of the Regulations on Holidays of Government Offices. * * Since 2014, it has been applied only on Seollal, Chuseok and Children's Day. @@ -492,45 +841,56 @@ private function calculateHangulDay(): void * As an exception, Children's Day also applies on Saturday. * * Since new legislation about public holiday was enacted in June 2021, - * this function is used to calculate the holidays up to 2021. + * this function is used to calculate the holidays up to 2022. * * @throws \Exception */ - private function calculateOldSubstituteHolidays(): void + private function calculateOldSubstituteHolidays(int $year): void { - if ($this->year < 2014) { - return; - } - // Add substitute holidays by fixed entries. - switch ($this->year) { + switch ($year) { + case 1959: + $this->addSubstituteHoliday($this->getHoliday('arborDay'), "$year-4-6"); + break; + case 1960: + $this->addSubstituteHoliday($this->getHoliday('constitutionDay'), "$year-7-18"); + $this->addSubstituteHoliday($this->getHoliday('hangulDay'), "$year-10-10"); + $this->addSubstituteHoliday($this->getHoliday('christmasDay'), "$year-12-26"); + break; + case 1989: + $this->addSubstituteHoliday($this->getHoliday('armedForcesDay'), "$year-10-2"); + break; case 2014: - $this->addSubstituteHoliday($this->getHoliday('dayBeforeChuseok'), "$this->year-9-10"); + $this->addSubstituteHoliday($this->getHoliday('dayBeforeChuseok'), "$year-9-10"); break; case 2015: - $this->addSubstituteHoliday($this->getHoliday('chuseok'), "$this->year-9-29"); + $this->addSubstituteHoliday($this->getHoliday('chuseok'), "$year-9-29"); break; case 2016: - $this->addSubstituteHoliday($this->getHoliday('dayBeforeSeollal'), "$this->year-2-10"); + $this->addSubstituteHoliday($this->getHoliday('dayBeforeSeollal'), "$year-2-10"); break; case 2017: - $this->addSubstituteHoliday($this->getHoliday('dayAfterSeollal'), "$this->year-1-30"); - $this->addSubstituteHoliday($this->getHoliday('dayBeforeChuseok'), "$this->year-10-6"); + $this->addSubstituteHoliday($this->getHoliday('dayAfterSeollal'), "$year-1-30"); + $this->addSubstituteHoliday($this->getHoliday('dayBeforeChuseok'), "$year-10-6"); break; case 2018: - $this->addSubstituteHoliday($this->getHoliday('childrensDay'), "$this->year-5-7"); - $this->addSubstituteHoliday($this->getHoliday('dayBeforeChuseok'), "$this->year-9-26"); + $this->addSubstituteHoliday($this->getHoliday('childrensDay'), "$year-5-7"); + $this->addSubstituteHoliday($this->getHoliday('dayBeforeChuseok'), "$year-9-26"); break; case 2019: - $this->addSubstituteHoliday($this->getHoliday('childrensDay'), "$this->year-5-6"); + $this->addSubstituteHoliday($this->getHoliday('childrensDay'), "$year-5-6"); break; case 2020: - $this->addSubstituteHoliday($this->getHoliday('dayAfterSeollal'), "$this->year-1-27"); + $this->addSubstituteHoliday($this->getHoliday('dayAfterSeollal'), "$year-1-27"); break; case 2021: - $this->addSubstituteHoliday($this->getHoliday('liberationDay'), "$this->year-8-16"); - $this->addSubstituteHoliday($this->getHoliday('nationalFoundationDay'), "$this->year-10-4"); - $this->addSubstituteHoliday($this->getHoliday('hangulDay'), "$this->year-10-11"); + $this->addSubstituteHoliday($this->getHoliday('liberationDay'), "$year-8-16"); + $this->addSubstituteHoliday($this->getHoliday('nationalFoundationDay'), "$year-10-4"); + $this->addSubstituteHoliday($this->getHoliday('hangulDay'), "$year-10-11"); + break; + case 2022: + $this->addSubstituteHoliday($this->getHoliday('dayAfterChuseok'), "$year-9-12"); + $this->addSubstituteHoliday($this->getHoliday('hangulDay'), "$year-10-10"); break; } } @@ -544,29 +904,16 @@ private function calculateOldSubstituteHolidays(): void * * @throws \Exception */ - private function calculateSubstituteHolidays(): void + private function calculateSubstituteHolidays(int $year): void { - if ($this->year < 2022) { - $this->calculateOldSubstituteHolidays(); + if ($year < 2023) { + $this->calculateOldSubstituteHolidays($year); return; } // List of holidays allowed for substitution. - $acceptedHolidays = []; - - // When deciding on alternative holidays, place lunar holidays first for consistent rules. - // These holidays will substitute for the sunday only. - $acceptedHolidays += array_fill_keys([ - 'dayBeforeSeollal', 'seollal', 'dayAfterSeollal', - 'dayBeforeChuseok', 'chuseok', 'dayAfterChuseok', - ], [0]); - - // These holidays will substitute for any weekend days (Sunday and Saturday). - $acceptedHolidays += array_fill_keys([ - 'childrensDay', 'independenceMovementDay', 'liberationDay', - 'nationalFoundationDay', 'hangulDay', - ], [0, 6]); + $acceptedHolidays = $this->calculateAcceptedSubstituteHolidays($year); // Step 1. Build a temporary table that aggregates holidays by date. $dates = []; @@ -608,6 +955,42 @@ private function calculateSubstituteHolidays(): void } } + /** + * Return a dictionary of substitute holiday + * Government-recognized holidays will be replaced with an alternative holiday if they overlap with a Saturday or Sunday. + * This dictionary contains information about which day of the week the holiday is replaced when it falls on. + * + * @return array> + */ + private function calculateAcceptedSubstituteHolidays(int $year): array + { + // List of holidays allowed for substitution. + // This dictionary has key => value mappings. + // each key is key of holiday and value contains day of week (saturday or sunday or both) + // value meaning : 0 = saturday, 1 = sunday + $acceptedHolidays = []; + + if ($year < 2023) { + return $acceptedHolidays; + } + + // When deciding on alternative holidays, place lunar holidays first for consistent rules. + // These holidays will substitute for the sunday only. + $acceptedHolidays += array_fill_keys([ + 'dayBeforeSeollal', 'seollal', 'dayAfterSeollal', + 'dayBeforeChuseok', 'chuseok', 'dayAfterChuseok', + ], [0]); + + // These holidays will substitute for any weekend days (Sunday and Saturday). + // 'buddhasBirthday' and 'christmasDay' included as alternative holiday in May 2023. + $acceptedHolidays += array_fill_keys([ + 'childrensDay', 'independenceMovementDay', 'liberationDay', + 'nationalFoundationDay', 'hangulDay', 'buddhasBirthday', 'christmasDay', + ], [0, 6]); + + return $acceptedHolidays; + } + /** * Helper method to find a first working day after specific date. */ diff --git a/tests/SouthKorea/ArborDayTest.php b/tests/SouthKorea/ArborDayTest.php index 0de52a57b..64409b6d1 100644 --- a/tests/SouthKorea/ArborDayTest.php +++ b/tests/SouthKorea/ArborDayTest.php @@ -29,9 +29,9 @@ class ArborDayTest extends SouthKoreaBaseTestCase implements HolidayTestCase public const REMOVED_YEAR = 2005; /** - * The year in which the holiday was not celebrated. + * The year the date was temporarily changed. */ - public const YEAR_NOT_CELEBRATED = 1960; + public const TEMPORARY_CHANGED_YEAR = 1960; /** * The name of the holiday. */ @@ -50,20 +50,16 @@ class ArborDayTest extends SouthKoreaBaseTestCase implements HolidayTestCase public function testHoliday(): void { $year = $this->generateRandomYear(self::ESTABLISHMENT_YEAR, self::REMOVED_YEAR); - if (self::YEAR_NOT_CELEBRATED === $year) { - $this->assertNotHoliday( - self::REGION, - self::HOLIDAY, - $year - ); - } else { - $this->assertHoliday( - self::REGION, - self::HOLIDAY, - $year, - new \DateTime("$year-4-5", new \DateTimeZone(self::TIMEZONE)) - ); - } + $date = (self::TEMPORARY_CHANGED_YEAR === $year) + ? new \DateTime("$year-3-21", new \DateTimeZone(self::TIMEZONE)) + : new \DateTime("$year-4-5", new \DateTimeZone(self::TIMEZONE)); + + $this->assertHoliday( + self::REGION, + self::HOLIDAY, + $year, + $date + ); } /** @@ -102,14 +98,14 @@ public function testHolidayBeforeEstablishment(): void public function testTranslation(): void { $year = $this->generateRandomYear(self::ESTABLISHMENT_YEAR, self::REMOVED_YEAR); - if (self::YEAR_NOT_CELEBRATED !== $year) { - $this->assertTranslatedHolidayName( - self::REGION, - self::HOLIDAY, - $year, - [self::LOCALE => '식목일'] - ); - } + $translation = (self::TEMPORARY_CHANGED_YEAR === $year) ? '사방의 날' : '식목일'; + + $this->assertTranslatedHolidayName( + self::REGION, + self::HOLIDAY, + $year, + [self::LOCALE => $translation] + ); } /** @@ -120,13 +116,11 @@ public function testTranslation(): void public function testHolidayType(): void { $year = $this->generateRandomYear(self::ESTABLISHMENT_YEAR, self::REMOVED_YEAR); - if (self::YEAR_NOT_CELEBRATED !== $year) { - $this->assertHolidayType( - self::REGION, - self::HOLIDAY, - $year, - Holiday::TYPE_OFFICIAL - ); - } + $this->assertHolidayType( + self::REGION, + self::HOLIDAY, + $year, + Holiday::TYPE_OFFICIAL + ); } } diff --git a/tests/SouthKorea/ArmedForcesDayTest.php b/tests/SouthKorea/ArmedForcesDayTest.php index f067ab0bb..7e51df09a 100644 --- a/tests/SouthKorea/ArmedForcesDayTest.php +++ b/tests/SouthKorea/ArmedForcesDayTest.php @@ -31,7 +31,7 @@ class ArmedForcesDayTest extends SouthKoreaBaseTestCase implements HolidayTestCa /** * The year in which the holiday was first established. */ - public const ESTABLISHMENT_YEAR = 1956; + public const ESTABLISHMENT_YEAR = 1976; /** * The year in which the holiday was removed. diff --git a/tests/SouthKorea/BuddhasBirthdayTest.php b/tests/SouthKorea/BuddhasBirthdayTest.php index 87477ec66..eed7cf329 100644 --- a/tests/SouthKorea/BuddhasBirthdayTest.php +++ b/tests/SouthKorea/BuddhasBirthdayTest.php @@ -16,7 +16,6 @@ namespace Yasumi\tests\SouthKorea; use Yasumi\Holiday; -use Yasumi\Provider\SouthKorea; use Yasumi\tests\HolidayTestCase; /** @@ -34,6 +33,11 @@ class BuddhasBirthdayTest extends SouthKoreaBaseTestCase implements HolidayTestC */ public const ESTABLISHMENT_YEAR = 1975; + /** + * The year of upper limit for tests of lunar date. + */ + public const LUNAR_TEST_LIMIT = 2050; + /** * Tests the holiday defined in this test. * @@ -41,13 +45,39 @@ class BuddhasBirthdayTest extends SouthKoreaBaseTestCase implements HolidayTestC */ public function testHoliday(): void { - $year = $this->generateRandomYear(self::ESTABLISHMENT_YEAR, 2050); - if (isset(SouthKorea::LUNAR_HOLIDAY[self::HOLIDAY][$year])) { - $this->assertHoliday( + $year = $this->generateRandomYear(self::ESTABLISHMENT_YEAR, self::LUNAR_TEST_LIMIT); + $this->assertHoliday( + self::REGION, + self::HOLIDAY, + $year, + new \DateTime(self::LUNAR_HOLIDAY[self::HOLIDAY][$year], new \DateTimeZone(self::TIMEZONE)) + ); + } + + /** + * Tests substitute holidays. + * + * @dataProvider SubstituteHolidayDataProvider + * + * @param int $year the year for which the holiday defined in this test needs to be tested + * @param ?string $expected the expected date + * + * @throws \Exception + */ + public function testSubstituteHoliday(int $year, ?string $expected): void + { + if ($expected) { + $this->assertSubstituteHoliday( self::REGION, self::HOLIDAY, $year, - new \DateTime(SouthKorea::LUNAR_HOLIDAY[self::HOLIDAY][$year], new \DateTimeZone(self::TIMEZONE)) + new \DateTime($expected, new \DateTimeZone(self::TIMEZONE)) + ); + } else { + $this->assertNotSubstituteHoliday( + self::REGION, + self::HOLIDAY, + $year ); } } @@ -73,15 +103,13 @@ public function testHolidayBeforeEstablishment(): void */ public function testTranslation(): void { - $year = $this->generateRandomYear(self::ESTABLISHMENT_YEAR, 2050); - if (isset(SouthKorea::LUNAR_HOLIDAY[self::HOLIDAY][$year])) { - $this->assertTranslatedHolidayName( - self::REGION, - self::HOLIDAY, - $year, - [self::LOCALE => '부처님오신날'] - ); - } + $year = $this->generateRandomYear(self::ESTABLISHMENT_YEAR, self::LUNAR_TEST_LIMIT); + $this->assertTranslatedHolidayName( + self::REGION, + self::HOLIDAY, + $year, + [self::LOCALE => '부처님오신날'] + ); } /** @@ -91,14 +119,39 @@ public function testTranslation(): void */ public function testHolidayType(): void { - $year = $this->generateRandomYear(self::ESTABLISHMENT_YEAR, 2050); - if (isset(SouthKorea::LUNAR_HOLIDAY[self::HOLIDAY][$year])) { - $this->assertHolidayType( - self::REGION, - self::HOLIDAY, - $year, - Holiday::TYPE_OFFICIAL - ); - } + $year = $this->generateRandomYear(self::ESTABLISHMENT_YEAR, self::LUNAR_TEST_LIMIT); + $this->assertHolidayType( + self::REGION, + self::HOLIDAY, + $year, + Holiday::TYPE_OFFICIAL + ); + } + + /** + * Returns a list of test dates. + * + * @return array list of test dates for the holiday defined in this test + */ + public function SubstituteHolidayDataProvider(): array + { + return [ + [1975, null], + [2005, null], + [2020, null], + [2021, null], + [2022, null], + [2023, '2023-05-29'], + [2024, null], + [2025, '2025-05-06'], + [2026, '2026-05-25'], + [2027, null], + [2028, null], + [2029, '2029-05-21'], + [2030, null], + [2031, null], + [2032, '2032-05-17'], + [2036, '2036-05-06'], + ]; } } diff --git a/tests/SouthKorea/ChildrensDayTest.php b/tests/SouthKorea/ChildrensDayTest.php index 696f651a2..f6e264ef7 100644 --- a/tests/SouthKorea/ChildrensDayTest.php +++ b/tests/SouthKorea/ChildrensDayTest.php @@ -31,7 +31,7 @@ class ChildrensDayTest extends SouthKoreaBaseTestCase implements HolidayTestCase /** * The year in which the holiday was first established. */ - public const ESTABLISHMENT_YEAR = 1970; + public const ESTABLISHMENT_YEAR = 1975; /** * Tests the holiday defined in this test. diff --git a/tests/SouthKorea/ChristmasDayTest.php b/tests/SouthKorea/ChristmasDayTest.php index c6f3f815a..c1ec36d05 100644 --- a/tests/SouthKorea/ChristmasDayTest.php +++ b/tests/SouthKorea/ChristmasDayTest.php @@ -49,6 +49,34 @@ public function testHoliday(): void ); } + /** + * Tests substitute holidays. + * + * @dataProvider SubstituteHolidayDataProvider + * + * @param int $year the year for which the holiday defined in this test needs to be tested + * @param ?string $expected the expected date + * + * @throws \Exception + */ + public function testSubstituteHoliday(int $year, ?string $expected): void + { + if ($expected) { + $this->assertSubstituteHoliday( + self::REGION, + self::HOLIDAY, + $year, + new \DateTime($expected, new \DateTimeZone(self::TIMEZONE)) + ); + } else { + $this->assertNotSubstituteHoliday( + self::REGION, + self::HOLIDAY, + $year + ); + } + } + /** * Tests the holiday defined in this test before establishment. * @@ -92,4 +120,41 @@ public function testHolidayType(): void Holiday::TYPE_OFFICIAL ); } + + /** + * Returns a list of test dates. + * + * @return array list of test dates for the holiday defined in this test + */ + public function SubstituteHolidayDataProvider(): array + { + return [ + [1949, null], + [1950, null], + [1959, null], + [1960, '1960-12-26'], + [1965, null], + [2020, null], + [2021, null], + [2022, null], + [2023, null], + [2024, null], + [2025, null], + [2026, null], + [2027, '2027-12-27'], + [2028, null], + [2029, null], + [2030, null], + [2031, null], + [2032, '2032-12-27'], + [2033, '2033-12-26'], + [2034, null], + [2035, null], + [2036, null], + [2037, null], + [2038, '2038-12-27'], + [2039, '2039-12-26'], + [2040, null], + ]; + } } diff --git a/tests/SouthKorea/ChuseokTest.php b/tests/SouthKorea/ChuseokTest.php index fbac5fcc5..554a37118 100644 --- a/tests/SouthKorea/ChuseokTest.php +++ b/tests/SouthKorea/ChuseokTest.php @@ -16,7 +16,6 @@ namespace Yasumi\tests\SouthKorea; use Yasumi\Holiday; -use Yasumi\Provider\SouthKorea; use Yasumi\tests\HolidayTestCase; /** @@ -34,6 +33,11 @@ class ChuseokTest extends SouthKoreaBaseTestCase implements HolidayTestCase */ public const ESTABLISHMENT_YEAR = 1949; + /** + * The year of upper limit for tests of lunar date. + */ + public const LUNAR_TEST_LIMIT = 2050; + /** * Tests the holiday defined in this test. * @@ -41,32 +45,30 @@ class ChuseokTest extends SouthKoreaBaseTestCase implements HolidayTestCase */ public function testHoliday(): void { - $year = $this->generateRandomYear(self::ESTABLISHMENT_YEAR, 2050); - if (isset(SouthKorea::LUNAR_HOLIDAY[self::HOLIDAY][$year])) { - $date = new \DateTime(SouthKorea::LUNAR_HOLIDAY[self::HOLIDAY][$year], new \DateTimeZone(self::TIMEZONE)); - - // Chuseok - $this->assertHoliday(self::REGION, self::HOLIDAY, $year, $date); - - // Day after Chuseok - if ($year >= 1986) { - $this->assertHoliday( - self::REGION, - 'dayAfterChuseok', - $year, - (clone $date)->add(new \DateInterval('P1D')) - ); - } - - // Day before Chuseok - if ($year >= 1989) { - $this->assertHoliday( - self::REGION, - 'dayBeforeChuseok', - $year, - (clone $date)->sub(new \DateInterval('P1D')) - ); - } + $year = $this->generateRandomYear(self::ESTABLISHMENT_YEAR, self::LUNAR_TEST_LIMIT); + $date = new \DateTime(self::LUNAR_HOLIDAY[self::HOLIDAY][$year], new \DateTimeZone(self::TIMEZONE)); + + // Chuseok + $this->assertHoliday(self::REGION, self::HOLIDAY, $year, $date); + + // Day after Chuseok + if ($year >= 1986) { + $this->assertHoliday( + self::REGION, + 'dayAfterChuseok', + $year, + (clone $date)->add(new \DateInterval('P1D')) + ); + } + + // Day before Chuseok + if ($year >= 1989) { + $this->assertHoliday( + self::REGION, + 'dayBeforeChuseok', + $year, + (clone $date)->sub(new \DateInterval('P1D')) + ); } } @@ -173,30 +175,31 @@ public function testHolidayBeforeEstablishment(): void */ public function testTranslation(): void { - $year = $this->generateRandomYear(self::ESTABLISHMENT_YEAR, 2050); - if (isset(SouthKorea::LUNAR_HOLIDAY[self::HOLIDAY][$year])) { + $year = $this->generateRandomYear(self::ESTABLISHMENT_YEAR, self::LUNAR_TEST_LIMIT); + + $this->assertTranslatedHolidayName( + self::REGION, + self::HOLIDAY, + $year, + [self::LOCALE => '추석'] + ); + + if ($year >= 1986) { + $this->assertTranslatedHolidayName( + self::REGION, + 'dayAfterChuseok', + $year, + [self::LOCALE => '추석 연휴'] + ); + } + + if ($year >= 1989) { $this->assertTranslatedHolidayName( self::REGION, - self::HOLIDAY, + 'dayBeforeChuseok', $year, - [self::LOCALE => '추석'] + [self::LOCALE => '추석 연휴'] ); - if ($year >= 1986) { - $this->assertTranslatedHolidayName( - self::REGION, - 'dayAfterChuseok', - $year, - [self::LOCALE => '추석 연휴'] - ); - } - if ($year >= 1989) { - $this->assertTranslatedHolidayName( - self::REGION, - 'dayBeforeChuseok', - $year, - [self::LOCALE => '추석 연휴'] - ); - } } } @@ -207,30 +210,31 @@ public function testTranslation(): void */ public function testHolidayType(): void { - $year = $this->generateRandomYear(self::ESTABLISHMENT_YEAR, 2050); - if (isset(SouthKorea::LUNAR_HOLIDAY[self::HOLIDAY][$year])) { + $year = $this->generateRandomYear(self::ESTABLISHMENT_YEAR, self::LUNAR_TEST_LIMIT); + + $this->assertHolidayType( + self::REGION, + self::HOLIDAY, + $year, + Holiday::TYPE_OFFICIAL + ); + + if ($year >= 1986) { + $this->assertHolidayType( + self::REGION, + 'dayAfterChuseok', + $year, + Holiday::TYPE_OFFICIAL + ); + } + + if ($year >= 1989) { $this->assertHolidayType( self::REGION, - self::HOLIDAY, + 'dayBeforeChuseok', $year, Holiday::TYPE_OFFICIAL ); - if ($year >= 1986) { - $this->assertHolidayType( - self::REGION, - 'dayAfterChuseok', - $year, - Holiday::TYPE_OFFICIAL - ); - } - if ($year >= 1989) { - $this->assertHolidayType( - self::REGION, - 'dayBeforeChuseok', - $year, - Holiday::TYPE_OFFICIAL - ); - } } } } diff --git a/tests/SouthKorea/MemorialDayTest.php b/tests/SouthKorea/MemorialDayTest.php index a3e326816..1e29dba1e 100644 --- a/tests/SouthKorea/MemorialDayTest.php +++ b/tests/SouthKorea/MemorialDayTest.php @@ -31,7 +31,7 @@ class MemorialDayTest extends SouthKoreaBaseTestCase implements HolidayTestCase /** * The year in which the holiday was first established. */ - public const ESTABLISHMENT_YEAR = 1966; + public const ESTABLISHMENT_YEAR = 1956; /** * Tests the holiday defined in this test. diff --git a/tests/SouthKorea/SeollalTest.php b/tests/SouthKorea/SeollalTest.php index 54e9bada6..79f66f40b 100644 --- a/tests/SouthKorea/SeollalTest.php +++ b/tests/SouthKorea/SeollalTest.php @@ -16,7 +16,6 @@ namespace Yasumi\tests\SouthKorea; use Yasumi\Holiday; -use Yasumi\Provider\SouthKorea; use Yasumi\tests\HolidayTestCase; /** @@ -34,6 +33,11 @@ class SeollalTest extends SouthKoreaBaseTestCase implements HolidayTestCase */ public const ESTABLISHMENT_YEAR = 1985; + /** + * The year of upper limit for tests of lunar date. + */ + public const LUNAR_TEST_LIMIT = 2050; + /** * Tests the holiday defined in this test. * @@ -41,30 +45,29 @@ class SeollalTest extends SouthKoreaBaseTestCase implements HolidayTestCase */ public function testHoliday(): void { - $year = $this->generateRandomYear(self::ESTABLISHMENT_YEAR, 2050); - if (isset(SouthKorea::LUNAR_HOLIDAY[self::HOLIDAY][$year])) { - $date = new \DateTime(SouthKorea::LUNAR_HOLIDAY[self::HOLIDAY][$year], new \DateTimeZone(self::TIMEZONE)); + $year = $this->generateRandomYear(self::ESTABLISHMENT_YEAR, self::LUNAR_TEST_LIMIT); + $date = new \DateTime(self::LUNAR_HOLIDAY[self::HOLIDAY][$year], new \DateTimeZone(self::TIMEZONE)); + if ($year >= 1985) { // Seollal $this->assertHoliday(self::REGION, self::HOLIDAY, $year, $date); + } - if ($year >= 1990) { - // Day before Seollal - $this->assertHoliday( - self::REGION, - 'dayBeforeSeollal', - $year, - (clone $date)->sub(new \DateInterval('P1D')) - ); - - // Day after Seollal - $this->assertHoliday( - self::REGION, - 'dayAfterSeollal', - $year, - (clone $date)->add(new \DateInterval('P1D')) - ); - } + if ($year >= 1989) { + // Day before Seollal + $this->assertHoliday( + self::REGION, + 'dayBeforeSeollal', + $year, + (clone $date)->sub(new \DateInterval('P1D')) + ); + // Day after Seollal + $this->assertHoliday( + self::REGION, + 'dayAfterSeollal', + $year, + (clone $date)->add(new \DateInterval('P1D')) + ); } } @@ -128,28 +131,28 @@ public function testHolidayBeforeEstablishment(): void */ public function testTranslation(): void { - $year = $this->generateRandomYear(self::ESTABLISHMENT_YEAR, 2050); - if (isset(SouthKorea::LUNAR_HOLIDAY[self::HOLIDAY][$year])) { - $this->assertTranslatedHolidayName( + $year = $this->generateRandomYear(self::ESTABLISHMENT_YEAR, self::LUNAR_TEST_LIMIT); + + $this->assertTranslatedHolidayName( + self::REGION, + self::HOLIDAY, + $year, + [self::LOCALE => '설날'] + ); + + if ($year >= 1990) { + $this->assertHolidayType( self::REGION, - self::HOLIDAY, + 'dayBeforeSeollal', $year, - [self::LOCALE => '설날'] + Holiday::TYPE_OFFICIAL + ); + $this->assertHolidayType( + self::REGION, + 'dayAfterSeollal', + $year, + Holiday::TYPE_OFFICIAL ); - if ($year >= 1990) { - $this->assertHolidayType( - self::REGION, - 'dayBeforeSeollal', - $year, - Holiday::TYPE_OFFICIAL - ); - $this->assertHolidayType( - self::REGION, - 'dayAfterSeollal', - $year, - Holiday::TYPE_OFFICIAL - ); - } } } @@ -160,28 +163,28 @@ public function testTranslation(): void */ public function testHolidayType(): void { - $year = $this->generateRandomYear(self::ESTABLISHMENT_YEAR, 2050); - if (isset(SouthKorea::LUNAR_HOLIDAY[self::HOLIDAY][$year])) { + $year = $this->generateRandomYear(self::ESTABLISHMENT_YEAR, self::LUNAR_TEST_LIMIT); + + $this->assertHolidayType( + self::REGION, + self::HOLIDAY, + $year, + Holiday::TYPE_OFFICIAL + ); + + if ($year >= 1990) { + $this->assertHolidayType( + self::REGION, + 'dayBeforeSeollal', + $year, + Holiday::TYPE_OFFICIAL + ); $this->assertHolidayType( self::REGION, - self::HOLIDAY, + 'dayAfterSeollal', $year, Holiday::TYPE_OFFICIAL ); - if ($year >= 1990) { - $this->assertHolidayType( - self::REGION, - 'dayBeforeSeollal', - $year, - Holiday::TYPE_OFFICIAL - ); - $this->assertHolidayType( - self::REGION, - 'dayAfterSeollal', - $year, - Holiday::TYPE_OFFICIAL - ); - } } } } diff --git a/tests/SouthKorea/SouthKoreaBaseTestCase.php b/tests/SouthKorea/SouthKoreaBaseTestCase.php index e59b90f92..5fc3d1981 100644 --- a/tests/SouthKorea/SouthKoreaBaseTestCase.php +++ b/tests/SouthKorea/SouthKoreaBaseTestCase.php @@ -33,4 +33,77 @@ abstract class SouthKoreaBaseTestCase extends TestCase /** Locale that is considered common for this provider. */ public const LOCALE = 'ko_KR'; + + /** Lunar dates for lunar holidays */ + public const LUNAR_HOLIDAY = [ + 'seollal' => [ + '1949' => '1949-01-29', '1950' => '1950-02-17', '1951' => '1951-02-06', '1952' => '1952-01-27', '1953' => '1953-02-14', + '1954' => '1954-02-04', '1955' => '1955-01-24', '1956' => '1956-02-12', '1957' => '1957-01-31', '1958' => '1958-02-19', + '1959' => '1959-02-08', '1960' => '1960-01-28', '1961' => '1961-02-15', '1962' => '1962-02-05', '1963' => '1963-01-25', + '1964' => '1964-02-13', '1965' => '1965-02-02', '1966' => '1966-01-22', '1967' => '1967-02-09', '1968' => '1968-01-30', + '1969' => '1969-02-17', '1970' => '1970-02-06', '1971' => '1971-01-27', '1972' => '1972-02-15', '1973' => '1973-02-03', + '1974' => '1974-01-23', '1975' => '1975-02-11', '1976' => '1976-01-31', '1977' => '1977-02-18', '1978' => '1978-02-07', + '1979' => '1979-01-28', '1980' => '1980-02-16', '1981' => '1981-02-05', '1982' => '1982-01-25', '1983' => '1983-02-13', + '1984' => '1984-02-02', '1985' => '1985-02-20', '1986' => '1986-02-09', '1987' => '1987-01-29', '1988' => '1988-02-18', + '1989' => '1989-02-06', '1990' => '1990-01-27', '1991' => '1991-02-15', '1992' => '1992-02-04', '1993' => '1993-01-23', + '1994' => '1994-02-10', '1995' => '1995-01-31', '1996' => '1996-02-19', '1997' => '1997-02-08', '1998' => '1998-01-28', + '1999' => '1999-02-16', '2000' => '2000-02-05', '2001' => '2001-01-24', '2002' => '2002-02-12', '2003' => '2003-02-01', + '2004' => '2004-01-22', '2005' => '2005-02-09', '2006' => '2006-01-29', '2007' => '2007-02-18', '2008' => '2008-02-07', + '2009' => '2009-01-26', '2010' => '2010-02-14', '2011' => '2011-02-03', '2012' => '2012-01-23', '2013' => '2013-02-10', + '2014' => '2014-01-31', '2015' => '2015-02-19', '2016' => '2016-02-08', '2017' => '2017-01-28', '2018' => '2018-02-16', + '2019' => '2019-02-05', '2020' => '2020-01-25', '2021' => '2021-02-12', '2022' => '2022-02-01', '2023' => '2023-01-22', + '2024' => '2024-02-10', '2025' => '2025-01-29', '2026' => '2026-02-17', '2027' => '2027-02-07', '2028' => '2028-01-27', + '2029' => '2029-02-13', '2030' => '2030-02-03', '2031' => '2031-01-23', '2032' => '2032-02-11', '2033' => '2033-01-31', + '2034' => '2034-02-19', '2035' => '2035-02-08', '2036' => '2036-01-28', '2037' => '2037-02-15', '2038' => '2038-02-04', + '2039' => '2039-01-24', '2040' => '2040-02-12', '2041' => '2041-02-01', '2042' => '2042-01-22', '2043' => '2043-02-10', + '2044' => '2044-01-30', '2045' => '2045-02-17', '2046' => '2046-02-06', '2047' => '2047-01-26', '2048' => '2048-02-14', + '2049' => '2049-02-02', '2050' => '2050-01-23', + ], + 'buddhasBirthday' => [ + '1949' => '1949-05-05', '1950' => '1950-05-24', '1951' => '1951-05-13', '1952' => '1952-05-01', '1953' => '1953-05-20', + '1954' => '1954-05-10', '1955' => '1955-05-29', '1956' => '1956-05-17', '1957' => '1957-05-07', '1958' => '1958-05-26', + '1959' => '1959-05-15', '1960' => '1960-05-03', '1961' => '1961-05-22', '1962' => '1962-05-11', '1963' => '1963-05-01', + '1964' => '1964-05-19', '1965' => '1965-05-08', '1966' => '1966-05-27', '1967' => '1967-05-16', '1968' => '1968-05-05', + '1969' => '1969-05-23', '1970' => '1970-05-12', '1971' => '1971-05-02', '1972' => '1972-05-20', '1973' => '1973-05-10', + '1974' => '1974-04-29', '1975' => '1975-05-18', '1976' => '1976-05-06', '1977' => '1977-05-25', '1978' => '1978-05-14', + '1979' => '1979-05-03', '1980' => '1980-05-21', '1981' => '1981-05-11', '1982' => '1982-05-01', '1983' => '1983-05-20', + '1984' => '1984-05-08', '1985' => '1985-05-27', '1986' => '1986-05-16', '1987' => '1987-05-05', '1988' => '1988-05-23', + '1989' => '1989-05-12', '1990' => '1990-05-02', '1991' => '1991-05-21', '1992' => '1992-05-10', '1993' => '1993-05-28', + '1994' => '1994-05-18', '1995' => '1995-05-07', '1996' => '1996-05-24', '1997' => '1997-05-14', '1998' => '1998-05-03', + '1999' => '1999-05-22', '2000' => '2000-05-11', '2001' => '2001-05-01', '2002' => '2002-05-19', '2003' => '2003-05-08', + '2004' => '2004-05-26', '2005' => '2005-05-15', '2006' => '2006-05-05', '2007' => '2007-05-24', '2008' => '2008-05-12', + '2009' => '2009-05-02', '2010' => '2010-05-21', '2011' => '2011-05-10', '2012' => '2012-05-28', '2013' => '2013-05-17', + '2014' => '2014-05-06', '2015' => '2015-05-25', '2016' => '2016-05-14', '2017' => '2017-05-03', '2018' => '2018-05-22', + '2019' => '2019-05-12', '2020' => '2020-04-30', '2021' => '2021-05-19', '2022' => '2022-05-08', '2023' => '2023-05-27', + '2024' => '2024-05-15', '2025' => '2025-05-05', '2026' => '2026-05-24', '2027' => '2027-05-13', '2028' => '2028-05-02', + '2029' => '2029-05-20', '2030' => '2030-05-09', '2031' => '2031-05-28', '2032' => '2032-05-16', '2033' => '2033-05-06', + '2034' => '2034-05-25', '2035' => '2035-05-15', '2036' => '2036-05-03', '2037' => '2037-05-22', '2038' => '2038-05-11', + '2039' => '2039-04-30', '2040' => '2040-05-18', '2041' => '2041-05-07', '2042' => '2042-05-26', '2043' => '2043-05-16', + '2044' => '2044-05-05', '2045' => '2045-05-24', '2046' => '2046-05-13', '2047' => '2047-05-02', '2048' => '2048-05-20', + '2049' => '2049-05-09', '2050' => '2050-05-28', + ], + 'chuseok' => [ + '1949' => '1949-10-06', '1950' => '1950-09-26', '1951' => '1951-09-15', '1952' => '1952-10-03', '1953' => '1953-09-22', + '1954' => '1954-09-11', '1955' => '1955-09-30', '1956' => '1956-09-19', '1957' => '1957-09-08', '1958' => '1958-09-27', + '1959' => '1959-09-17', '1960' => '1960-10-05', '1961' => '1961-09-24', '1962' => '1962-09-13', '1963' => '1963-10-02', + '1964' => '1964-09-20', '1965' => '1965-09-10', '1966' => '1966-09-29', '1967' => '1967-09-18', '1968' => '1968-10-06', + '1969' => '1969-09-26', '1970' => '1970-09-15', '1971' => '1971-10-03', '1972' => '1972-09-22', '1973' => '1973-09-11', + '1974' => '1974-09-30', '1975' => '1975-09-20', '1976' => '1976-09-08', '1977' => '1977-09-27', '1978' => '1978-09-17', + '1979' => '1979-10-05', '1980' => '1980-09-23', '1981' => '1981-09-12', '1982' => '1982-10-01', '1983' => '1983-09-21', + '1984' => '1984-09-10', '1985' => '1985-09-29', '1986' => '1986-09-18', '1987' => '1987-10-07', '1988' => '1988-09-25', + '1989' => '1989-09-14', '1990' => '1990-10-03', '1991' => '1991-09-22', '1992' => '1992-09-11', '1993' => '1993-09-30', + '1994' => '1994-09-20', '1995' => '1995-09-09', '1996' => '1996-09-27', '1997' => '1997-09-16', '1998' => '1998-10-05', + '1999' => '1999-09-24', '2000' => '2000-09-12', '2001' => '2001-10-01', '2002' => '2002-09-21', '2003' => '2003-09-11', + '2004' => '2004-09-28', '2005' => '2005-09-18', '2006' => '2006-10-06', '2007' => '2007-09-25', '2008' => '2008-09-14', + '2009' => '2009-10-03', '2010' => '2010-09-22', '2011' => '2011-09-12', '2012' => '2012-09-30', '2013' => '2013-09-19', + '2014' => '2014-09-08', '2015' => '2015-09-27', '2016' => '2016-09-15', '2017' => '2017-10-04', '2018' => '2018-09-24', + '2019' => '2019-09-13', '2020' => '2020-10-01', '2021' => '2021-09-21', '2022' => '2022-09-10', '2023' => '2023-09-29', + '2024' => '2024-09-17', '2025' => '2025-10-06', '2026' => '2026-09-25', '2027' => '2027-09-15', '2028' => '2028-10-03', + '2029' => '2029-09-22', '2030' => '2030-09-12', '2031' => '2031-10-01', '2032' => '2032-09-19', '2033' => '2033-09-08', + '2034' => '2034-09-27', '2035' => '2035-09-16', '2036' => '2036-10-04', '2037' => '2037-09-24', '2038' => '2038-09-13', + '2039' => '2039-10-02', '2040' => '2040-09-21', '2041' => '2041-09-10', '2042' => '2042-09-28', '2043' => '2043-09-17', + '2044' => '2044-10-05', '2045' => '2045-09-25', '2046' => '2046-09-15', '2047' => '2047-10-04', '2048' => '2048-09-22', + '2049' => '2049-09-11', '2050' => '2050-09-30', + ], + ]; } diff --git a/tests/SouthKorea/SouthKoreaTest.php b/tests/SouthKorea/SouthKoreaTest.php index 82e17379e..9ab30faee 100644 --- a/tests/SouthKorea/SouthKoreaTest.php +++ b/tests/SouthKorea/SouthKoreaTest.php @@ -18,12 +18,18 @@ use Yasumi\Holiday; use Yasumi\Provider\SouthKorea; use Yasumi\tests\ProviderTestCase; +use Yasumi\Yasumi; /** * Class for testing holidays in South Korea. */ class SouthKoreaTest extends SouthKoreaBaseTestCase implements ProviderTestCase { + /** + * @var int the year of upper limit for tests of lunar date + */ + public const LUNAR_TEST_LIMIT = 2050; + /** * @var int year random year number used for all tests in this Test Case */ @@ -36,7 +42,7 @@ class SouthKoreaTest extends SouthKoreaBaseTestCase implements ProviderTestCase */ protected function setUp(): void { - $this->year = $this->generateRandomYear(1949, 2050); + $this->year = $this->generateRandomYear(1949, self::LUNAR_TEST_LIMIT); } /** @@ -45,56 +51,65 @@ protected function setUp(): void public function testOfficialHolidays(): void { $officialHolidays = []; + if ($this->year >= 1949) { $officialHolidays[] = 'independenceMovementDay'; $officialHolidays[] = 'liberationDay'; $officialHolidays[] = 'nationalFoundationDay'; + $officialHolidays[] = 'newYearsDay'; + $officialHolidays[] = 'chuseok'; $officialHolidays[] = 'christmasDay'; - if (ArborDayTest::YEAR_NOT_CELEBRATED !== $this->year && $this->year < ArborDayTest::REMOVED_YEAR + 1) { - $officialHolidays[] = 'arborDay'; + + if ($this->year >= 1950 && $this->year < 1976) { + $officialHolidays[] = 'unitedNationsDay'; } - if ($this->year <= 1990 || $this->year > 2012) { - $officialHolidays[] = 'hangulDay'; + + if ($this->year >= 1956) { + $officialHolidays[] = 'memorialDay'; } - if ($this->year < 2008) { - $officialHolidays[] = 'constitutionDay'; + + if ($this->year >= 1975) { + $officialHolidays[] = 'childrensDay'; + $officialHolidays[] = 'buddhasBirthday'; } - } - if ($this->year >= 1950) { - $officialHolidays[] = 'newYearsDay'; - if ($this->year <= 1990) { - $officialHolidays[] = 'twoDaysLaterNewYearsDay'; + + if ($this->year >= 1976 && $this->year <= 1990) { + $officialHolidays[] = 'armedForcesDay'; } - if ($this->year <= 1998) { - $officialHolidays[] = 'dayAfterNewYearsDay'; + + if ($this->year >= 1985) { + $officialHolidays[] = 'seollal'; } - } - if ($this->year >= 1956 && $this->year <= 1990) { - $officialHolidays[] = 'armedForcesDay'; - } - if ($this->year >= 1966) { - $officialHolidays[] = 'memorialDay'; - } - // specific cases (Seollal, Buddha's Birthday and Chuseok) - if ($this->year >= 1949 && isset(SouthKorea::LUNAR_HOLIDAY['chuseok'][$this->year])) { - $officialHolidays[] = 'chuseok'; if ($this->year >= 1986) { $officialHolidays[] = 'dayAfterChuseok'; } + if ($this->year >= 1989) { $officialHolidays[] = 'dayBeforeChuseok'; - } - } - if ($this->year >= 1975 && isset(SouthKorea::LUNAR_HOLIDAY['buddhasBirthday'][$this->year])) { - $officialHolidays[] = 'buddhasBirthday'; - } - if ($this->year >= 1985 && isset(SouthKorea::LUNAR_HOLIDAY['seollal'][$this->year])) { - $officialHolidays[] = 'seollal'; - if ($this->year > 1989) { $officialHolidays[] = 'dayBeforeSeollal'; $officialHolidays[] = 'dayAfterSeollal'; } + + if ($this->year <= 1989) { + $officialHolidays[] = 'twoDaysLaterNewYearsDay'; + } + + if ($this->year <= 1990 || $this->year > 2012) { + $officialHolidays[] = 'hangulDay'; + } + + if ($this->year <= 1998) { + $officialHolidays[] = 'dayAfterNewYearsDay'; + } + + if ($this->year <= 2005) { + $officialHolidays[] = 'arborDay'; + } + + if ($this->year < 2008) { + $officialHolidays[] = 'constitutionDay'; + } } $this->assertDefinedHolidays($officialHolidays, self::REGION, $this->year, Holiday::TYPE_OFFICIAL); @@ -140,4 +155,17 @@ public function testSources(): void { $this->assertSources(self::REGION, 3); } + + /** + * Tests if all generation methods is exists in provider. + */ + public function testGenerationMethods(): void + { + $holidayProvider = Yasumi::create(self::REGION, $this->year); + + $this->assertIsArray(SouthKorea::HOLIDAY_NAMES, 'Yasumi\Provider\SouthKorea::HOLIDAY_NAMES is not array'); + foreach (SouthKorea::HOLIDAY_NAMES as $key => $names) { + $this->assertTrue(method_exists($holidayProvider, $key), sprintf('Generation method `%s` is not declared in provider `%s`', $key, self::REGION)); + } + } } diff --git a/tests/SouthKorea/UnitedNationsDayTest.php b/tests/SouthKorea/UnitedNationsDayTest.php new file mode 100644 index 000000000..348f2bcc9 --- /dev/null +++ b/tests/SouthKorea/UnitedNationsDayTest.php @@ -0,0 +1,114 @@ + + */ + +namespace Yasumi\tests\SouthKorea; + +use Yasumi\Holiday; +use Yasumi\tests\HolidayTestCase; + +/** + * Class for testing United Nations Day in South Korea. + */ +class UnitedNationsDayTest extends SouthKoreaBaseTestCase implements HolidayTestCase +{ + /** + * The name of the holiday. + */ + public const HOLIDAY = 'unitedNationsDay'; + + /** + * The year in which the holiday was first established. + */ + public const ESTABLISHMENT_YEAR = 1950; + + /** + * The year in which the holiday was removed. + */ + public const REMOVED_YEAR = 1975; + + /** + * Tests the holiday defined in this test. + * + * @throws \Exception + */ + public function testHoliday(): void + { + $year = $this->generateRandomYear(self::ESTABLISHMENT_YEAR, self::REMOVED_YEAR); + $this->assertHoliday( + self::REGION, + self::HOLIDAY, + $year, + new \DateTime("$year-10-24", new \DateTimeZone(self::TIMEZONE)) + ); + } + + /** + * Tests the holiday defined in this test after removal. + * + * @throws \Exception + */ + public function testHolidayAfterRemoval(): void + { + $this->assertNotHoliday( + self::REGION, + self::HOLIDAY, + $this->generateRandomYear(self::REMOVED_YEAR + 1) + ); + } + + /** + * Tests the holiday defined in this test before establishment. + * + * @throws \Exception + */ + public function testHolidayBeforeEstablishment(): void + { + $this->assertNotHoliday( + self::REGION, + self::HOLIDAY, + $this->generateRandomYear(1000, self::ESTABLISHMENT_YEAR - 1) + ); + } + + /** + * Tests the translated name of the holiday defined in this test. + * + * @throws \Exception + */ + public function testTranslation(): void + { + $this->assertTranslatedHolidayName( + self::REGION, + self::HOLIDAY, + $this->generateRandomYear(self::ESTABLISHMENT_YEAR, self::REMOVED_YEAR), + [self::LOCALE => '유엔의 날'] + ); + } + + /** + * Tests type of the holiday defined in this test. + * + * @throws \Exception + */ + public function testHolidayType(): void + { + $this->assertHolidayType( + self::REGION, + self::HOLIDAY, + $this->generateRandomYear(self::ESTABLISHMENT_YEAR, self::REMOVED_YEAR), + Holiday::TYPE_OFFICIAL + ); + } +}