niirrty/niirrty.holiday

一个可扩展的国际节假日库。

1.3.1 2024-03-10 12:51 UTC

This package is auto-updated.

Last update: 2024-09-10 14:00:50 UTC


README

一个可扩展的国际节假日库。

以德语显示此文档

为初始支持国家以外的其他国家定义节假日非常容易。更多信息请见 根据国家定义节假日

安装

这是一个通过composer提供的包

composer require niirrty/niirrty.holiday ^1.3 

或在 composer.jsonrequire 区域内

{
   "require": {
                "php": ">=8.1",
                "niirrty/niirrty.holiday": "^1.3"
              }
}

用法

<?php

use Niirrty\Holiday\CountryDefinitionsFactory;

// Load the country depending ('de' == 'Germany') holiday definitions
$holidayDefinitions = CountryDefinitionsFactory::Create( 'de' );

// Get the german holidays for year 2018 in english language
$holidays = $holidayDefinitions->getHolidays( 2018, 'en' );

// Output small info about the holidays
foreach ( $holidays as $holiday )
{
   echo $holiday->getDate()->format( 'Y-m-d' ), ' : ', $holiday->getName(), "\n";
}

$holidays 返回的集合包含定义国家德国(de)的所有节假日,使用英语名称(en)表示,用于使用的年份 2018

每个集合项都是一个类型为 \Niirrty\Holiday\Holiday 的对象

CountryDefinitionsFactory::Create(…) 还支持第二个参数。通过它可以定义一个文件夹,用你自己的文件夹替换默认的库依赖文件夹,从中获取节假日定义数据。

上述 ->getHolidays( … ) 返回的 HolidayCollection 实例还提供了以下方法

  • startsAt( int $month = 1, int $day = 1 ) : HolidayCollection:此方法返回从定义的月份和日期开始或之后的所有节假日
  • byRegionId( int $regionId ) : HolidayCollection:提取具有定义 ID 的区域的所有节假日。区域 ID 意味着该区域在定义区域列表中的索引。你可以通过调用 $regions = $holidays->extractRegionNames(); 获取索引和相关区域名称。键是 ID/索引,值是名称。
  • byRegionIds( array $regionIds ) : HolidayCollection:与 byRegionId 相同,但用于多个区域。
  • byRegionName( string $regionName ) : HolidayCollection:提取具有定义名称的区域的所有节假日
  • byRegionNames( array $regionNames ) : HolidayCollection:提取具有定义名称的区域的所有节假日
  • restDays() : HolidayCollection:获取所有工作日免费的休息日节假日
  • noRestDays() : HolidayCollection:获取所有不工作日免费、无休息日的节假日

支持的国家

当前支持的国家有

  • 'at' 奥地利(休息日和无休息日)
  • 'ch' 瑞士(仅休息日)
  • 'cz' 捷克(仅休息日)
  • 'de' 德国(休息日和无休息日)
  • 'fr' 法国(仅休息日)
  • 'it' 意大利(仅休息日)
  • 'jp' 日本(仅休息日)
  • 'nl' 荷兰(仅休息日)
  • 'uk' 英国(仅休息日)

您也可以通过编程方式获取支持的国家

<?php

use Niirrty\Holiday\CountryDefinitionsFactory;

$supportedCountries = CountryDefinitionsFactory::GetSupportedCountries();

可用区域

并非所有国家都需要使用基于区域节假日的功能,但如果需要,您可以调用获取可用区域

$holidayDefinitions->getRegions();

所有内置国家都应该(不必)支持以下语言的名称翻译:'de'、'en'、'fr'、'it'、'es'、'pt'、'cz' 和 'jp'

如果国家使用其他语言,也可以定义。

定义国家相关的节假日

每个国家都通过使用 \Niirrty\Holiday\Definition\Niirrty\Holiday\DefinitionCollection 类,在 data 文件夹中单独的 PHP 文件中定义所有可用的节假日。

文件命名规范

{COUNTRY-ID}.php

文件名必须以为节假日指定的 2 个字符 ISO 国家 ID(小写)开头。

文件必须使用 PHP 文件名扩展名 .php,必须包含有效的 PHP 代码,并且必须返回新的 \Niirrty\Holiday\DefinitionCollection 实例,该实例定义了所有国家相关的节假日定义。

文件结构

基本结构如下

<?php


use Niirrty\Holiday\Definition;
use Niirrty\Holiday\DefinitionCollection;
use Niirrty\Holiday\Identifiers;

return DefinitionCollection::Create( 'United Kingdom', 'uk' )

   ->setRegions(
      [
         // TODO 1: If required, define the list of region names here like
         // Also notice the indexes of the names after each name for easier associate the indexes with the names
         // because: If you define a holiday, only valid for one or more regions you have to use the indexes.
         'Alderney',         // 0
         'England',          // 1
         'Guernsey',         // 2
         'Isle of Man',      // 3
         'Jersey',           // 4
         'North Ireland',    // 5
         'Scotland',         // 6
         'Wales'             // 7
   ] )

   ->addRange(
      
      // TODO 2: Here all holidays must be defined comma separated
      
   );

现在您必须获取有关假期的信息(维基百科是一个好的起点)

所需假期信息

  • 所有支持语言的假期名称
  • 如果未由Niirrty\Holiday\Identifiers::*类常量定义,则具有唯一Holiday 标识符字符串。
  • 如果静态,则假期日期月份,或者根据需求计算动态年份的回调。
  • 可选的年范围(开始日期和/或结束日期),其中假期有效。
  • 如果条件匹配,可选的条件用于移动假期。
  • 可选的区域,其中假期仅对有效。
  • 信息显示假期是否为无工作假日。

现在如果您有了所有假期信息,可以通过替换TODO 2注释来定义假期

假期定义

最简单的假期是具有静态日期的假期

<?php

            // 03-17 : Saint Patrick's Day…
            Definition::Create( Identifiers::SAINT_PATRICKS_DAY )
                      ->setStaticDate( 3, 17 )
                      ->setName( 'Saint Patrick\'s Day' )
                      ->setNameTranslations( [
                         'en' => 'Saint Patrick\'s Day',
                         'de' => 'St. Patrick\'s Day',
                         'fr' => 'Le jour de la Saint-Patrick',
                         'it' => 'Giorno di San Patrizio',
                         'es' => 'Día de San Patricio',
                         'pt' => 'Dia de São Patrick',
                         'cz' => 'Den svatého Patrika',
                         'jp' => '聖パトリックの日'
                      ] )

标识符必须是唯一的。如果假期在许多国家经常使用,则可能在Niirrty\Holiday\Identifiers内部定义为常量

setName( '…' )根据国家主要语言设置假期名称

条件假期移动

但是这个假期(以及英国和其他许多国家的其他假期)只在3月17日有效。如果它不是星期六或星期日,在这两种情况下,假期将移动到下一个星期一。

可以通过扩展定义并使用MoveConditions来解决此问题

<?php

            // 03-17 : Saint Patrick's Day…
            Definition::Create( Identifiers::SAINT_PATRICKS_DAY )
                      ->setStaticDate( 3, 17 )
                      ->setName( 'Saint Patrick\'s Day' )
                      
                      // move to next day (monday) if date is a sunday
                      ->addMoveCondition( MoveCondition::OnSunday( 1 ) )
                      // move 2 days in future (monday) if date is a saturday
                      ->addMoveCondition( MoveCondition::OnSaturday( 2 ) )
                      
                      ->setNameTranslations( [
                         'en' => 'Saint Patrick\'s Day',
                         'de' => 'St. Patrick\'s Day',
                         'fr' => 'Le jour de la Saint-Patrick',
                         'it' => 'Giorno di San Patrizio',
                         'es' => 'Día de San Patricio',
                         'pt' => 'Dia de São Patrick',
                         'cz' => 'Den svatého Patrika',
                         'jp' => '聖パトリックの日'
                      ] )

MoveCondition也可以通过一个自己的回调来启动,该回调检查条件是否匹配

<?php

            // 03-17 : Saint Patrick's Day…
            Definition::Create( Identifiers::SAINT_PATRICKS_DAY )
                      ->setStaticDate( 3, 17 )
                      ->setName( 'Saint Patrick\'s Day' )
                      
                      // move to next day (monday) if date is a sunday
                      ->addMoveCondition( MoveCondition::Create(
                         1,
                         function ( \DateTime $date ) : bool
                         {
                            return 0 === ( (int) $date->format( 'w' ) );
                         } ) )
                      // move 2 days in future (monday) if date is a saturday
                      ->addMoveCondition( MoveCondition::Create(
                         1,
                         function ( \DateTime $date ) : bool
                         {
                            return 6 === ( (int) $date->format( 'w' ) );
                         } ) )
                      
                      ->setNameTranslations( [
                         'en' => 'Saint Patrick\'s Day',
                         'de' => 'St. Patrick\'s Day',
                         'fr' => 'Le jour de la Saint-Patrick',
                         'it' => 'Giorno di San Patrizio',
                         'es' => 'Día de San Patricio',
                         'pt' => 'Dia de São Patrick',
                         'cz' => 'Den svatého Patrika',
                         'jp' => '聖パトリックの日'
                      ] )

前面的条件做的是一样的

区域依赖性假期

如果假期只对一个或多个特定区域有效,则可以通过setValidRegions( [ … ] )声明

<?php

            // 03-17 : Saint Patrick's Day…
            Definition::Create( Identifiers::SAINT_PATRICKS_DAY )
                      ->setStaticDate( 3, 17 )
                      ->setName( 'Saint Patrick\'s Day' )
                      ->setNameTranslations( [
                         'en' => 'Saint Patrick\'s Day',
                         'de' => 'St. Patrick\'s Day',
                         'fr' => 'Le jour de la Saint-Patrick',
                         'it' => 'Giorno di San Patrizio',
                         'es' => 'Día de San Patricio',
                         'pt' => 'Dia de São Patrick',
                         'cz' => 'Den svatého Patrika',
                         'jp' => '聖パトリックの日'
                      ] )
                      
                      // Holiday is valid for regions England (1) and Wales (7)
                      ->setValidRegions( [ 1, 7 ] )

具有动态日期的假期

您必须定义一个回调,该回调根据年份计算动态假期并返回它。这是通过调用setDynamicDateCallback( … )完成的

在这里,您必须传递一个实现Niirrty\Holiday\Callbacks\IDynamicDateCallback

<?php

            // Early May Bank Holiday - The 1st monday in mai
            Definition::Create( 'Early May Bank Holiday' )
                      ->setName( 'Early May Bank Holiday' )
                      ->setDynamicDateCallback(
                         new \Niirrty\Holiday\Callbacks\NamedDateCallback( 'first monday of may ' ) )
                      ->setNameTranslations( [
                         'en' => 'Early May Bank Holiday',
                         'jp' => '月上旬バンクホリデー'
                      ] )

其他当前已知的回调包括

  • \Niirrty\Holiday\Callbacks\ModifyDateCallback:如果日期应由DateTime修改(modify()方法格式)计算,则可以通过此动态日期回调定义。
  • \Niirrty\Holiday\Callbacks\EasterDateCallback:计算基督教复活节星期日
  • \Niirrty\Holiday\Callbacks\NamedDateCallback:如果日期应由命名日期时间字符串构建。例如,'last monday of january'将导致'last monday of january ' . $year
  • \Niirrty\Holiday\Callbacks\AdventDateCallback:对于根据动态基督教 Advent 天计算日期
  • \Niirrty\Holiday\Callbacks\EasterDateCallback:计算北半球或南半球的四个季节开始日期春季、夏季、秋季和冬季。

但是实现自己的非常简单

<?php

declare( strict_types = 1 );

namespace My\Callbacks;

use Niirrty\Holiday\Callbacks\IDynamicDateCallback;
use Niirrty\Date\DateTime;


class MyDynamicDateCallback implements IDynamicDateCallback
{
   
   public function calculate( int $year ) : \DateTime
   {
   
      return ( 0 === $year % 2 )
         ? DateTime::Create( $year, 5, 1 )
         : DateTime::Create( $year, 5, 2 );
   
   }
   
}

特殊情况 - 复活节相关假期

使用CreateEasterDepening( … )可以轻松创建复活节相关假期(动态基准日期)

<?php

            // Good Friday (Easter sunday - 2 days)
            Definition::CreateEasterDepending( Identifiers::GOOD_FRIDAY, -2 )
                      ->setName( 'Good Friday' )
                      ->setNameTranslations( [
                         'en' => 'Good Friday',
                         'de' => 'Karfreitag',
                         'fr' => 'Vendredi Saint',
                         'it' => 'Venerdì Santo',
                         'es' => 'Viernes Santo',
                         'pt' => 'Sexta-feira Santa',
                         'cz' => 'Velký pátek',
                         'jp' => '良い金曜日'
                      ] ),

一年范围内的假期有效

您可以使用setValidFromYear( … )设置假期开始有效的年份。如果未定义,则最低可用的日期是默认值。

您可以使用setValidToYear( … )设置假期结束有效的年份。如果未定义,则没有限制。

如果ValidToYearValidFromYear之前,则表示假期在ValidToYear结束时有效,并在ValidFromYear时重新成为有效状态。

如果有更多范围,您必须多次定义假期,但请注意:永远不要使用相同的标识符!

休息日假期

假日最初都是“休息日”(无工作)的假日。如果需要定义“非休息日”的假日,您可以通过在定义声明中添加 ->setIsRestDay( false ) 来实现。

结束…