niirrty / niirrty.holiday
一个可扩展的国际节假日库。
Requires
- php: >=8.3
- niirrty/niirrty.date: ^0.6
- niirrty/niirrty.io: ^0.6
- psr/log: ^1.0
Requires (Dev)
- mockery/mockery: ^1.0
- phpunit/phpunit: 9.*
This package is auto-updated.
Last update: 2024-09-10 14:00:50 UTC
README
一个可扩展的国际节假日库。
为初始支持国家以外的其他国家定义节假日非常容易。更多信息请见 根据国家定义节假日
安装
这是一个通过composer提供的包
composer require niirrty/niirrty.holiday ^1.3
或在 composer.json
的 require
区域内
{ "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( … )
设置假期结束有效的年份。如果未定义,则没有限制。
如果ValidToYear
在ValidFromYear
之前,则表示假期在ValidToYear
结束时有效,并在ValidFromYear
时重新成为有效状态。
如果有更多范围,您必须多次定义假期,但请注意:永远不要使用相同的标识符!
休息日假期
假日最初都是“休息日”(无工作)的假日。如果需要定义“非休息日”的假日,您可以通过在定义声明中添加 ->setIsRestDay( false )
来实现。
结束…