PHP获得明年同一周的同一天

时间:2014-05-23 19:25:41

标签: php date datetime

我正在研究客户调度程序,我的雇主希望它每年自动重新安排客户。他希望他们每年保持同一周的同一天。

例如,客户计划于2014年5月23日举行。这是5月的第四个周五。 2014年5月23日过后,应预订2015年5月4日的预约(在本案例中为第22次)。

我已经尝试过各种各样的方法来实现这一点(例如使用DateTime提前一年,找到一周中任何一天的“之前”)。但是,我尝试过的每一款车型在短短几年后都会出现故障。他们最终会像...这个月的第二个星期五一样。

有没有人有办法让这个工作?我的雇主非常具体地希望调度程序以这种方式工作。 x.x如果有人知道如何,我真的很感激帮助。

感谢您阅读本文!

3 个答案:

答案 0 :(得分:6)

正如已经指出的那样,例如,可能没有6月的第5个星期五,所以需要有一些标准的方法来决定明年哪一周与当前星期相同。

实际上已经有ISO 8601中的周编号标准,PHP的DateTime class内置了处理它们的功能。

我的建议是在下一年ISO 8601 week number安排同一天的下一次会议。以下功能将为您完成: -

/**
 * @param \DateTime $date Date of the original meeting
 * @return \DateTime Date of the next meeting
 */
function getSameDayNextYear(\DateTime $date = null)
{
    if(!$date){
        $date = new \DateTime();
    }
    return (new \DateTime())->setISODate((int)$date->format('o') + 1, (int)$date->format('W'), (int)$date->format('N'));
}

See it working with some test code

我相信你会同意这是最简单的方法,而且应该看到你正确的next 100 years or more:)

引用格式DateTimeDate

答案 1 :(得分:0)

我认为这将满足您的需求。不过,你需要对它进行彻底的测试才能确定。

$event = new DateTime('2014-05-18');
$dayOfWeek = $event->format('l');
if ($dayOfWeek !== 'Sunday') {
    $event->modify('previous Sunday'); 
}
else {
    $event->modify('-1 day'); 
}
$event->modify('+1 year');
if ($dayOfWeek !== 'Sunday' && $dayOfWeek !== $event->format('l')) {
    $event->modify('next ' . $dayOfWeek);
}
echo $event->format('Y-m-d');

Demo

答案 2 :(得分:0)

将您的要求更改为"添加一年并找到一周的下一个匹配日"我想出了这个:

function nextDate($date = false){
    if(!$date){ $date = new DateTime(); }
    $oneYear = new DateInterval('P1Y');
    $dayOfWeek = $date->format('w');
    $nextDate = clone $date;
    $nextDate->add($oneYear);
    $nextYearDayOfWeek = $nextDate->format('w');
    while($nextYearDayOfWeek != $dayOfWeek){
        // add a day and check again
        $nextDate->add(new DateInterval('P1D'));
        $nextYearDayOfWeek = $nextDate->format('w');
    }
    return $nextDate;
}

我的测试:

$test1 = new DateTime('5/23/2014');
$test2 = new DateTime('5/24/2014');
$test3 = new DateTime('5/25/2014');
$test4 = new DateTime('5/26/2014');
$test5 = new DateTime('5/27/2014');
$test6 = new DateTime('5/28/2014');
$test7 = new DateTime('5/29/2014');
$test8 = new DateTime('1/1/2014');
$test9 = new DateTime('12/31/2014');
$test10 = new DateTime('5/5/2040');

$nextDate1 = nextDate($test1);
$nextDate2 = nextDate($test2);
$nextDate3 = nextDate($test3);
$nextDate4 = nextDate($test4);
$nextDate5 = nextDate($test5);
$nextDate6 = nextDate($test6);
$nextDate7 = nextDate($test7);
$nextDate8 = nextDate($test8);
$nextDate9 = nextDate($test9);
$nextDate10 = nextDate($test10);

print($nextDate1->format('m/d/y'));
print('<br />');
print($nextDate2->format('m/d/y'));
print('<br />');
print($nextDate3->format('m/d/y'));
print('<br />');
print($nextDate4->format('m/d/y'));
print('<br />');
print($nextDate5->format('m/d/y'));
print('<br />');
print($nextDate6->format('m/d/y'));
print('<br />');
print($nextDate7->format('m/d/y'));
print('<br />');
print($nextDate8->format('m/d/y'));
print('<br />');
print($nextDate9->format('m/d/y'));
print('<br />');
print($nextDate10->format('m/d/y'));

结果:

05/29/15
05/30/15
05/31/15
06/01/15
06/02/15
06/03/15
06/04/15
01/07/15
01/06/16
05/11/41

修改

我已经修改了下面的功能,以找到一周中最接近的一天而不是下一天(虽然除了减去之外它往往与前一个相同)。

function nextDate($date = false){
    if(!$date){ $date = new DateTime(); }
    $oneYear = new DateInterval('P1Y');
    $dayOfWeek = $date->format('w');
    $nextDate = clone $date;
    $nextDate->add($oneYear);
    $nextYearDayOfWeek = $nextDate->format('w');
    $diff = $dayOfWeek-$nextYearDayOfWeek;
    // if $diff is more than 3, it's faster to go the other way
    if(abs($diff) > 3){
        if($diff > 0){
            $diff = $diff-7;
        }else{
            $diff = 7+$diff;
        }
    }

    if($diff != 0){
        if($diff < 0){
            $nextDate->sub(new DateInterval('P'.abs($diff).'D'));
        }else{
            $nextDate->add(new DateInterval('P'.$diff.'D'));
        }
    }

    return $nextDate;
}

这次测试结果:

05/22/15
05/23/15
05/24/15
05/25/15
05/26/15
05/27/15
05/28/15
12/31/14
12/30/15
05/04/41