phpexperts/workday-planner

给定一个日期范围,这将给出该国家的所有工作日。

v1.1.1 2019-06-13 17:58 UTC

This package is auto-updated.

Last update: 2024-09-09 19:20:49 UTC


README

Travis CI Maintainability Test Coverage

安装

运行 composer require phpexperts/workday-planner

问题

想象一下,你需要在特定时间段内安排在本国每个工作日运行的任务。

为了做到这一点,你首先必须弄清楚工作日和周末。很简单,对吧?但是,然后你记得:“嘿,圣诞节怎么办?还有那些其他假日呢?”

所以,你尽职尽责地也检测了这些。结果,你的客户在独立日后的星期一开始抱怨。因为,你看,至少在美国,星期六发生的假日会观察到上一个星期五,而星期日发生的假日会观察到下一个星期一。

解决方案

使用此包,所有这些技术细节都为你处理了。你给它一个日期范围,它会尽职尽责地输出工作日,考虑到大多数雇主都有的实际和观察到的美国国家假日。

即兴工作日验证

    use PHPExperts\WorkdayPlanner\WorkdayDetector;
    
    function isWorkday($dateString) {
        $isWorkday = WorkdayDetector::isWorkday(new \DateTime($dateString));
        $isOrIsnt = $isWorkday ? 'is' : 'is not';

        echo "$dateString $isOrIsnt a work day.\n";
    }
    
    // Is Friday, 10 August 2018, a workday?
    isWorkday('10 August 2018');    // Workday
    isWorkday('11 August 2018');    // Weekend
    isWorkday('25 December 2018');  // Fixed holiday
    isWorkday('22 November 2018');  // Floating holiday
    
     /* Output:
     10 August 2018 is a work day.
     11 August 2018 is not a work day.
     25 December 2018 is not a work day.
     22 November 2018 is not a work day. 
     */

浮动假日

一些假日基于一个月的某一天,而不是固定日期。这些被称为“浮动假日”。

感恩节的日期规范看起来像这样

  {
    "name": "Thanksgiving Day",
    "type": "day",
    "when": "fourth Thursday of November"
  }

示例

    WorkdayDetector::isWorkday(new \DateTime('2018-11-22')); // false; Thanksgiving Day
    WorkdayDetector::isWorkday(new \DateTime('2019-11-28')); // false; Thanksgiving Day

    echo (new HolidayDetector())         // 2018-11-22
        ->getHoliday('Thanksgiving Day')
        ->format('Y-m-d');

    echo (new HolidayDetector())         // 2018-11-28
        ->changeYear(2019)
        ->getHoliday('Thanksgiving Day')
        ->format('Y-m-d');

可观察的假日

    // The Fourth of July occurs on a Sunday in 2021, so the following Monday is not
    // a workday.
    
    use PHPExperts\WorkdayPlanner\WorkdayPlanner;
    
    $planner = new WorkdayPlanner(new \DateTime('2021-07-01'), new \DateTime('2021-07-06'));
    
    echo json_encode(
        $planner->getWorkdays(), 
        JSON_PRETTY_PRINT
    );
    
    /* Output:
    [
        "2021-07-01",
        "2021-07-02",
        "2021-07-06"
    ]
    */

即兴假日验证

    $detector = new HolidayDetector();
    var_dump([
        $detector->isHoliday('2021-07-04'), // The actual holiday.
        $detector->isHoliday('2021-07-05'), // The observed holiday
    ]);
    
    $detector = new HolidayDetector();
    $detector->changeYear(2021);
    print_r([
        'actual' => $detector->getHoliday('Independence Day')->format('l jS \of F Y'),
        'observed' => $detector->getHoliday('Independence Day (Observed)')->format('l jS \of F Y'),
    ]);

    /* Output:
    array(2) {
      [0] => bool(true)
      [1] => bool(true)
    }
    
    Array
    (
        [actual] => Sunday 4th of July 2021
        [observed] => Monday 5th of July 2021
    )
    */

访问工作日

有几种方法可以访问工作日。

工作日规划器可以像数组一样访问,也可以作为迭代器访问,或者你可以直接获取所有工作日日期的简单数组。

简单访问

    $planner = new WorkdayPlanner(new \DateTime('2021-07-01'), new \DateTime('2021-07-06'));
    
    echo json_encode(
        $planner->getWorkdays(), 
        JSON_PRETTY_PRINT
    );
    
    /* Output:
    [
        "2021-07-01",
        "2021-07-02",
        "2021-07-06"
    ]
    */

作为迭代器

    $planner = new WorkdayPlanner(new \DateTime('2021-07-01'), new \DateTime('2021-07-06'));
    /** @var \DateTime $workday */
    foreach ($planner as $workday) {
        // ...
    }

作为数组

    $planner = new WorkdayPlanner(new \DateTime('2021-07-01'), new \DateTime('2021-07-06'));

    // Is it a workday?
    if (isset($planner['2021-07-01'])) {
        echo "Yes, it is.\n";
    }
    else {
        echo "No, it is not.\n";
    }
    
    // Since '2021-07-01' is the first day in the range, it is equal to $planner[0].
    echo ($planner[0] === $planner['2021-07-01']) ? 'Strictly equal!' : 'Not equal.';
    
    /* Output:
    Yes, it is.
    Strictly equal!
    */

手动删除工作日

工作日可以手动删除,根据您的政策

    $planner = new WorkdayPlanner(new \DateTime('2021-07-01'), new \DateTime('2021-07-06'));
    unset($planner['2021-07-01']);

    // Is it a workday?
    if (isset($planner['2021-07-01'])) {
        echo "Yes, it is.\n";
    }
    else {
        echo "No, it is not.\n";
    }

    /* Output:
    No, it is not.
    */

行为文档

项目目前通过单元测试实现了100%的代码覆盖率。

以下是行为文档,由PHPUnit的testdox生成

假日检测器

  1. 可以解析固定的假日日期
  2. 可以解析浮动的假日日期
  3. 可以确定一个日期是否是假日
  4. 对于未实现的国家显示错误
  5. 对于无效数据显示错误
  6. 对于无效的假日规范显示错误
  7. 正确处理未知的假日
  8. 将星期六的假日观察到星期五
  9. 将星期日的假日观察到星期一

工作日检测器

  1. 可以确定一个日期是否是工作日

工作日规划器

  1. 将创建工作日日期范围
  2. 将正确偏移星期六的假日
  3. 将正确偏移星期日的假日
  4. 可以遍历每个日期
  5. 工作日的数量是可以计数的
  6. 可以通过数组运算符使用数字索引访问日期
  7. 可以通过数组运算符使用日期索引访问日期
  8. 可以在工作日上进行数字isset
  9. 可以在工作日上进行日期isset
  10. 可以通过unset删除工作日
  11. 正确处理开始日期晚于结束日期的情况
  12. 正确处理开始日期等于结束日期的情况
  13. 正确处理无效日期
  14. 不允许手动添加工作日

致谢

由 Theodore R. Smith 创建 theodore@phpexperts.pro,大部分在一天内完成。

一个 PHP Experts, Inc. 项目。