Calculate Business Hours using Carbon, PHP in Laravel

I have recently come across a situation where in I had to calculate the business hours between two datetime’s. I started writing a helper function in Laravel which takes in two Carbon instances as arguments and returns the work hours considering 0800 – 1700 as work hours, Weekends are holidays and also takes in holiday dates which will be considered and not counted.

This post helps only to those who have basic idea of Laravel. If you want me to elaborate I would be glad to but I need someone to ask me for it. As the blog is left out with 0 comments, I want you to talk and ask me for it.

The function

hour < 8)
	{
		$to->addDays(-1);
		$to->hour = 17;
		$to->minute = 0;
		$to->second = 0;
	}
	if($to->hour >= 17)
	{	
		$to->hour = 17;
		$to->minute = 0;
		$to->second = 0;
	}
	if($from->hour >= 17)
	{	
		$from->addDays(1);
		$from->hour = 8;
		$from->minute = 0;
		$from->second = 0;
	}
	if($from->hour < 8)
	{	
		$from->hour = 8;
		$from->minute = 0;
		$from->second = 0;
	}
	if($from->gt($to))
		return 0;
	$holidays = 0; //Future Scope
	$diffDays = $to->diffInDaysFiltered(function($date){ return !checkHoliday($date); }, $from)-1;
	$weekends = $to->diffInDaysFiltered(function($date){ return checkHoliday($date); }, $from);//Weekends or holidays
	//echo 'Diff Days: '.$diffDays.' :: weekends : '.$weekends.'
'; $finalDiff = $diffDays * 9; $from->addDays($diffDays+$weekends); //echo 'from: '.$from.' to: '.$to.'
'; $diffHours = $to->diffInHoursFiltered(function($date) { if($date->hour > 8 && $date->hour < 17) return true; else return false; },$from)-1; $finalDiff += $diffHours; //echo 'Diff Hours: '.$diffHours.'
'; $from->addHours($diffHours); if($from->hour >= 17 || ($from->day < $to->day && !checkHoliday($to))) { $from->subHours($diffHours); $thatDay = clone $from; $thatDay->hour = 17; $thatDay->minute = 0; $thatDay->second=0; $prevMinutes = $from->diffInMinutes($thatDay); $toAddMinutes = ($diffHours * 60)-$prevMinutes; $from->addDays(1); while(checkHoliday($from)) $from->addDay(); $from->hour = 8; $from->minute = 0; $from->second = 0; $from->addMinutes($toAddMinutes); } //echo 'from: '.$from.' to: '.$to.'
'; $diffMinutes = $to->diffInMinutes($from); //echo 'Diff Minutes: '.$diffMinutes.'
'; $finalDiff += $diffMinutes / 60; //echo '

'; if($finalDiff<0) $finalDiff = 0; return $finalDiff; } function checkHoliday($date) { //print_r($date); //dd(config('holidays.'.$date->year.'.'.$date->month)); if($date->isWeekend() || in_array($date->day,config('holidays.'.$date->year.'.'.$date->month))) return true; else return false; }

The structure of the config file.

 [					 
		'1' => [1,18],			 //Month Based dates
		'2' => [15],
		'3' => [],
		'4' => [],
		'5' => [30],
		'6' => [],
		'7' => [4],
		'8' => [],
		'9' => [5],
		'10' => [],
		'11' => [11,24,25],
		'12' => [26],
	],

Do remember that in PHP if you send the instances of Carbon as your arguments then you will not be able to use those instances again as their reference is sent. Use clone keyword while calling the function.

Hope that helped.

Update 4th January, 2017: Fixed a minor bug.