Reputation:
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
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
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
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
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>";
}
}
Upvotes: 0