user6266762
user6266762

Reputation:

Finding last 7 working days in PHP

I am trying to find out last 7 working days (excluding Saturday and Sunday) from the current day. I am able to get last 7 days of the week, but unable to get the 7 working day's.

//code to found last 7 days  
$date = '04/30/2009'; // set current date
// parse about any English textual datetime description into a Unix timestamp 
$ts = strtotime($date);
// calculate the number of days since Monday
$dow = date('w', $ts);
$offset = $dow - 1;
if ($offset < 0) {
    $offset = 6;
}
// calculate timestamp for the Monday
$ts = $ts - $offset*86400;
// loop from Monday till Sunday 
for ($i = 0; $i < 7; $i++, $ts += 86400){
    print date("m/d/Y l", $ts) . "\n". "<br>";
}

But I wanted to find last 7 working days. Thanks in advance!

Upvotes: 3

Views: 2150

Answers (4)

Professor Abronsius
Professor Abronsius

Reputation: 33813

It's relatively easy to work backwards from a point int time to find the "working days" but finding "holidays" is far more complicated and would require considerably more code than this I suspect.

Using the DateTime class you can use the sub method to subtract whatever interval value you wish, in this case P1D is one day.

$strdate='04/30/2009';
$days=11;

$timezone=new DateTimeZone('Europe/London');
$interval=new DateInterval('P1D');

$start=new DateTime( date( DATE_COOKIE, strtotime( $strdate ) ), $timezone );
$end=new DateTime( date( DATE_COOKIE, strtotime( $start->format( DATE_COOKIE ) . '-' . $days .' days' ) ), $timezone );


$dates=array();
while( $start->sub( $interval ) > $end ){
    /* is the day integer less than 6(sat)? */
    if( $start->format('N') < 6 && count( $dates ) < 7 ) $dates[]=$start->format( DATE_COOKIE );
}

echo '<pre>',print_r( $dates,true ),'</pre>';

This outputs:

Array
(
    [0] => Wednesday, 29-Apr-09 00:00:00 BST
    [1] => Tuesday, 28-Apr-09 00:00:00 BST
    [2] => Monday, 27-Apr-09 00:00:00 BST
    [3] => Friday, 24-Apr-09 00:00:00 BST
    [4] => Thursday, 23-Apr-09 00:00:00 BST
    [5] => Wednesday, 22-Apr-09 00:00:00 BST
    [6] => Tuesday, 21-Apr-09 00:00:00 BST
)

I did a little playing around with a public api for getting public holiday information and cobbled the following together...I don't know what sort of coverage this api has for different countries but might be worth investigation.

Different country and region codes can be found here

$api='http://kayaposoft.com/enrico/json/v1.0/';
$params=array(
    'action'    =>  'getPublicHolidaysForDateRange',
    'fromDate'  =>  '',
    'toDate'    =>  '',
    'country'   =>  'eng'    #England
);

$strdate='2017/12/30';
$days=7;

$timezone=new DateTimeZone('Europe/London');
$interval=new DateInterval('P1D');

$start=new DateTime( date( 'Y-m-d', strtotime( $strdate ) ), $timezone );
$end=new DateTime( date( 'Y-m-d', strtotime( $start->format( 'Y-m-d' ) . '-' . $days .' days' ) ), $timezone );



$params['fromDate']=$end->format('d-m-Y');
$params['toDate']=$start->format('d-m-Y');

$query=http_build_query( $params );
$url=$api.'?'.$query;



$json=json_decode( file_get_contents( $url ) );
if( json_last_error() !== 0 ){
    $json=false;
}

function isholiday( $obj=false, $y=0, $m=0, $d=0 ){
    if( $obj && !empty( $obj ) ){
        foreach( $obj as $item ){
            $date=$item->date;
            if( $date->day==$d && $date->month=$m && $date->year==$y ) return $item->localName;
        }
    }
    return false;
}



$dates=array();
while( $start->sub( $interval ) > $end ){
    if( $start->format('N') < 6 && count( $dates ) < $days ) {

        $holiday=isholiday( $json, $start->format('Y'), $start->format('m'), $start->format('d') );

        $date=$start->format( 'Y-m-d' );

        $dates[]=$holiday ? $date .' - '.$holiday : $date;
    }
}

echo '<pre>',print_r( $dates, true ),'</pre>';

This outputs the following:

Array
(
    [0] => 2017-12-29
    [1] => 2017-12-28
    [2] => 2017-12-27
    [3] => 2017-12-26 - Boxing Day
    [4] => 2017-12-25 - Christmas Day
)

Upvotes: 1

Mahbubul Islam
Mahbubul Islam

Reputation: 1018

Finding holidays will be more complicated. One solution can be like saving the holidays in advance and skip them if they comes in the condition.

One simple solution for your problem can be like this.

<?php

$holiday = array(
        '2017-12-16' => 'Victory Day of Bangladesh',
        '2017-12-25' => 'Christmas'
    );


$i = 0;
$work_day = '2017-12-26';
while($i != 7)
{
    $work_day = date('Y-m-d', strtotime('-1 day', strtotime($work_day)));
    $day_name = date('l', strtotime($work_day));

    if($day_name != 'Saturday' && $day_name != 'Sunday' && !isset($holiday[$work_day]))
    {
        echo $work_day."\n";
        $i++;
    }
}

?>

Upvotes: 0

JerzySBG
JerzySBG

Reputation: 109

Simple code with possibility to add holidays:

<?php
$date = new DateTime('03/02/2009');
$interval = new DateInterval('P1D');

function isWorkingDay($date)
{
    $weekDay = $date->format('w');
    if ($weekDay == 0) // sunday
        return false;
    if ($weekDay == 6) // saturday
        return false;
    if ($date->format('m-d') == '07-05') // your check, example 5th July
        return false;
    return true;
}

$workingDays = [];

while(count($workingDays) != 7) {
    if(isWorkingDay($date)) {
        $workingDays[] = clone $date;
    }
    $date->sub($interval);
}
foreach($workingDays as $workingDay) {
    echo $workingDay->format('Y-m-d') . ', ';
}

Result - list of days without weekend days:

2009-03-02, 2009-02-27, 2009-02-26, 2009-02-25, 2009-02-24, 2009-02-23, 2009-02-20,

Upvotes: 0

ino
ino

Reputation: 2581

If you need 7 days without weekend days you need to check the numeric representation of the day of the week, ie "N" Format of date('N'). When skipping 2 weekend days you need increase the for loop to 9 days:

//code to found last 7 days
$date = '04/30/2009'; // set current date
// parse about any English textual datetime description into a Unix timestamp
$ts = strtotime($date);
// calculate the number of days since Monday
$dow = date('w', $ts);
$offset = $dow - 1;
if ($offset < 0) {
  $offset = 6;
}
// calculate timestamp for the Monday
$ts = $ts - $offset*86400;
// loop from Monday till Sunday
for ($i = 0; $i < 9; $i++, $ts += 86400){
  if(date("N", $ts) < 6){ // day code is less then weekday 6 & 7
  print  date("m/d/Y l", $ts) . "\n". "<br>";
  }
}

https://eval.in/916514

Upvotes: 0

Related Questions