PHP:判断日期减去周末和节假日

PHP: determination of the date minus weekends and holidays

有一个 WordPress 和 ACF 字段,日期格式为 2022-04-30。从这个日期开始,需要计算另外 2 个日期,-2 天和 +25 天。问题是只需要考虑工作日,即检查周末和节假日。

比如我们设置日期2022年5月3日,也就是星期二。从这个日期开始,我需要减去2天,即2022年5月1日,但这是星期天,所以我们必须return到5月1日之前的第一个工作日,即2022年4月29日星期五。是一样的有假期。

目前我有这个代码:

$setDate = get_field('set_date'); // ACF field, set May 3, 2022 (2022-05-03)
$offDate = wp_date('j F Y', strtotime('-2 days', strtotime($setDate)));
echo $offDate; // returns Sunday, May 1, 2022

我在 json https://github.com/d10xa/holidays-calendar/blob/master/json/consultant2022.json

找到假期和周末

所以我需要将给定日期与 json 中的日期进行比较,如果匹配,则减去一天并再次检查收到的日期。如果有匹配项,则再次减去一天,依此类推,直到找不到匹配项。我的想法是否正确,你能告诉我如何实施吗?我是一个非常糟糕的程序员,但是有一个任务)

目前我只能比较日期和 return 找到的结果 found/not。但是想不通怎么在这个基础上请假,再发来验证(

$setDate = '2022-05-01';

$file = file_get_contents('https://raw.githubusercontent.com/d10xa/holidays-calendar/master/json/consultant2022.json', true);
$data = json_decode($file);

$found = array_search($setDate, $data->holidays);
if ($found === False) {
    echo 'Not Found';
} else {
    echo 'found';
}

以下内容已经过几个日期的测试,我认为它可以正常工作。

/*

    JSON file is saved locally to a sub-directory
    for the current working script directory.
    This is to avoid unneccessary hits to the 
    remote site.
*/
$format='Y-m-d';
$url='https://raw.githubusercontent.com/d10xa/holidays-calendar/master/json/consultant2022.json';
$setDate = '2022-05-01';
$filepath=sprintf('%s/json/%s', __DIR__, basename( $url ) );


if( !file_exists( $filepath ) ){
    file_put_contents( $filepath, file_get_contents( $url ) );
}

# read the file and generate JSON
$json=json_decode( file_get_contents( $filepath ) );
$hols=$json->holidays;

# create the initial DateTime object and find which weekday we are dealing with
# where 1 (for Monday) through 7 (for Sunday)
$obj=new DateTime( $setDate );
$date=$obj->format( $format );
$day=$obj->format('N');




# Is the given date a holiday/weekend?
if( array_search( $date, $hols ) ){
    
    if( $day > 5 ){
        # Date is either Sat or Sun... go back to previous working day
        $subtract = 2 - ( 7 - $day );
        $int=new DateInterval( sprintf('P%sD', $subtract ) );
        $obj=new DateTime( $setDate );
        $previous=$obj->sub( $int );
    }else{
        $previous=$obj->sub( new DateInterval('P2D') );
    }
    
    
    # create the future date ( add 25 days )
    $int=new DateInterval('P25D');
    $obj=new DateTime( $setDate );
    $future=$obj->add( $int );
    
    
    if( array_search( $future->format( $format ), $hols ) ){
        # Future date is a holiday... go back to previous working day
        $day=$future->format('N');
        $subtract = 2 - ( 7 - $day );
        $int=new DateInterval( sprintf('P%sD',$subtract ) );
        $future=$future->sub( $int );
    }
    
}else{
    
    # Given date is NOT a holiday...
    # take a copy of the original DateTime object for generating future date.
    $ref=new DateTime( $setDate );
    
    
    
    $int=new DateInterval( 'P2D' );
    $previous=$obj->sub( $int );
    $day=$previous->format('N');
    # Is this a holiday?
    if( $day > 5 ){
        # yes - go back to previous working day
        $subtract = 2 - ( 7 - $day );
        $int=new DateInterval( sprintf('P%sD',$subtract ) );
        $previous=$previous->sub( $int );
    }
    
    
    $int=new DateInterval('P25D');
    $future=$ref->add( $int );
    $day=$future->format('N');
    # Is this a holiday?
    if( $day > 5 ){
        $subtract = 2 - ( 7 - $day );
        $int=new DateInterval( sprintf('P%sD',$subtract ) );
        $future=$future->sub( $int );
    }
}


printf(
    '<pre>
    Given date: %s
    Previous (-2): %s
    Future (+25): %s
    </pre>', 
    $date,
    $previous->format( $format ),
    $future->format( $format )
);

产生:

Given date: 2022-05-01
Previous (-2): 2022-04-29
Future (+25): 2022-05-26