从一组日期计算一年

时间:2016-04-05 15:31:25

标签: php laravel laravel-5 php-carbon

我得到一个包含一年的句号的数组如下。

$year = '2016';
$periods = [
      [
          'name' => "Name One",
          'startDate' => '01/01/2016',
          'endDate' => '03/31/2016'
      ],
        [
            'name' => "Name Two",
            'startDate' => '04/01/2016',
            'endDate' => '12/31/2016'
        ]
    ];

句点数可能会有所不同,因此,数组句点可能包含任意数量的元素(比如5个元素,表示给定年份的5个句点)。现在我需要确保期间确实构成一年,即两个期间不能重叠期间总计确定为指定年度

我尝试了许多不同的方法,但未能提出任何有效的解决方案。 我正在使用Laravel 5,因此使用Carbon包。但即使在Basic PHP中,我也很高兴能够完成这项工作。所以欢迎所有建议

1 个答案:

答案 0 :(得分:2)

尝试一下 - 可能有一个更优雅的解决方案,但我认为这是有效的。我使用过Carbon,因为它有一些非常有用的辅助方法。

我假设您的$periods数组将按日期顺序排列。如果不是,您可以usort

$year = '2016';
$periods = [
    [
        'name' => "Name One",
        'startDate' => '01/01/2016',
        'endDate' => '03/31/2016'
    ],
    [
        'name' => "Name Two",
        'startDate' => '04/01/2016',
        'endDate' => '12/31/2016'
    ]
];

// set a start position
$currentPosition = Carbon::create($year, 1, 1)->startOfDay();
// and the end of the year
$endOfYear = Carbon::create($year, 1, 1)->addYear()->startOfDay();

// iterate periods
foreach ($periods as $period) {
    $start = Carbon::createFromFormat('m/d/Y', $period['startDate'])->startOfDay();
    $end = Carbon::createFromFormat('m/d/Y', $period['endDate'])->endOfDay();

    // start of this period should follow the last (??)
    if ($start < $currentPosition) {
        throw new Exception("$start is earlier than $currentPosition");
    }

    // must follow on from the current position
    if ($currentPosition->diffInDays($start) > 0) {
        throw new Exception("$start doesn't follow $currentPosition");
    }

    // check it doesn't go over the end of the year
    if ($currentPosition->addDays($start->diffInDays($end)) > $endOfYear) {
        throw new Exception("$end takes us over the end of the year!");
    }

    $currentPosition = clone $end;
}

// did we reach the end?
if ($currentPosition->addDay()->startOfDay() != $endOfYear) {
    throw new Exception("Full year not accounted for");
}

// we're done
echo 'Full year accounted for'.PHP_EOL;