Home > Enterprise >  PHP: determination of the date minus weekends and holidays
PHP: determination of the date minus weekends and holidays

Time:05-02

There is a WordPress and ACF field with a date in the format 2022-04-30. From this date need to calculate 2 other dates, -2 days and 25 days. The problem is that it is necessary to take into account only working days, i.e. check weekends and holidays.

For example, we set the date May 3, 2022, which is Tuesday. From this date, I need to subtract 2 days, i.e. May 1, 2022, but this is Sunday, so we have to return to the first working day before May 1, i.e. Friday April 29, 2022. It's the same with holidays.

At the moment I have this code:

$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

I found holidays and weekends in json https://github.com/d10xa/holidays-calendar/blob/master/json/consultant2022.json

So I need to compare the given date with the dates from json and if there is a match, then minus one day and check the received date again. If there is a match, again minus one day and so on until no matches are found. Am I thinking correctly and can you tell me how to implement it? I am a very bad programmer, but there is a task)

At the moment I was only able to compare the dates and return the result found/not found. But I can't figure out how to take days off on the basis of this and send it for verification again(

$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';
}

CodePudding user response:

The following has been tested on a few dates and I think it works as it should.

/*

    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 )
);

Which yields:

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