Barand Posted February 20, 2013 Share Posted February 20, 2013 Tidied up the prototype's interface function workingHours($jstart, $jfinish, $holidays=array()) /********* * jstart - start time eg 2013-02-14 1 6:50:00 * jfinish - finish time eg 2013-02-18 18:00:00 * holidays- array of dates in yyyy-mm-dd format */ { $jobstart = new DateTime($jstart); $jobfinish = new DateTime($jfinish); $inc = DateInterval::createFromDateString('next weekday'); $dp = new DatePeriod($jobstart, $inc, $jobfinish); $totalmins = 0; foreach ($dp as $day) { $datepart = $day->format('Y-m-d'); $sod = clone $day; $sod->settime(9,0); // start of working day $eod = clone $day; $eod->settime(17,0); //end of working day if (in_array($datepart, $holidays)) { continue; } if ($datepart = $jobstart->format('Y-m-d')) { // first day $t = min(max($sod, $jobstart), $eod); // ensure time between 9 - 5pm list($h,$m) = explode(':', $eod->diff($t)->format('%h:%i')); $totalmins += $h*60 + $m; } if ($datepart = $jobfinish->format('Y-m-d')) { // last day $t = min(max($sod, $jobfinish), $eod); // ensure time between 9 - 5pm if ($datepart = $jobfinish->format('Y-m-d')) { // start date = finish date list($h,$m) = explode(':', $eod->diff($t)->format('%h:%i')); $totalmins -= ($h*60 + $m) ; } else { list($h,$m) = explode(':', $sod->diff($t)->format('%h:%i')); $totalmins += ($h*60 + $m) ; } } if ($datepart != $jobstart->format('Y-m-d') && $datepart != $jobfinish->format('Y-m-d')) { // somewhere inbetween $totalmins += 480; } } return $totalmins; } Quote Link to comment https://forums.phpfreaks.com/topic/274681-date-time-difference-using-only-working-hours/page/2/#findComment-1413694 Share on other sites More sharing options...
Clarkey Posted February 22, 2013 Author Share Posted February 22, 2013 Thanks for all your input guys! I've taken all your approaches and have come up with my own script. I'll post it up once I've tested it for every scenario and optimized it. Thanks again! I really didn't think I was going to get my head around this! Quote Link to comment https://forums.phpfreaks.com/topic/274681-date-time-difference-using-only-working-hours/page/2/#findComment-1414101 Share on other sites More sharing options...
Clarkey Posted March 25, 2013 Author Share Posted March 25, 2013 (edited) Almost a month delay, sorry! Here is the working script for Googlers reference You can paste it into a file and play around with the dates as it will echo what it is doing. <?php date_default_timezone_set("GMT"); $r = strtotime("03-05-2013 18:00:00"); $n = strtotime("07-05-2013 19:00:00"); //$n = strtotime(date("d-m-Y H:i:s", time())); $rTime = date("H:i:s", $r); $rTyme = date("His", $r); $rDate = date("d-m-Y", $r); $rDay = date("w", $r); $nTime = date("H:i:s", $n); $nTyme = date("His", $n); $nDate = date("d-m-Y", $n); $nDay = date("w", $n); $workdays = array(1,2,3,4,5); $holidays = array("01-01-2013", "29-03-2013", "01-04-2013", "06-05-2013", "27-05-2013", "26-08-2013", "25-12-2013", "26-12-2013", "01-01-2014", "18-04-2014", "21-04-2014", "05-05-2014", "26-05-2014", "25-08-2014", "25-12-2014", "26-12-2014", "01-01-2015", "03-04-2015", "06-04-2015", "04-05-2015", "25-05-2015", "31-08-2015", "25-12-2015", "28-12-2015"); // includes UK bank holidays until end of 2015 echo '-- INPUT<br>'; echo '$r = '.date("D d-m-Y H:i:s", $r).'<br>'; echo '$n = '.date("D d-m-Y H:i:s", $n).'<br>'; echo '<br>-- CHANGES<br>'; # -- $r ------------------------------------- # if $r is before 9am > move to 9am if($rTyme < "090000") { $r = strtotime("9am", $r); echo '$r is before 9am > move to 9am ('.date("D d-m-Y H:i:s", $r).')<br>'; # elseif $r is after 5pm > move to 9am next workday } elseif($rTyme > "170000") { $r = strtotime("+1 weekday 9am", $r); echo '$r is after 5pm > move to 9am next workday ('.date("D d-m-Y H:i:s", $r).')<br>'; } # if $r is a holiday > move to next workday 9am if(in_array(date("d-m-Y", $r), $holidays)) { $r = strtotime("+1 weekday 9am", $r); echo '$r is a holiday > move to next workday ('.date("D d-m-Y H:i:s", $r).')<br>'; # Boxing Day Check if(date("d-m", $r) == "26-12" || date("d-m-Y", $r) == "28-12-2015") { $r = strtotime("+1 weekday 9am", $r); echo '$r is boxing day > move to next workday ('.date("D d-m-Y H:i:s", $r).')<br>'; } } # if $r is a weekend > move to next workday 9am if(!in_array(date("w", $r), $workdays)) { $r = strtotime("+1 weekday 9am", $r); echo '$r is a weekend > move to next workday ('.date("D d-m-Y H:i:s", $r).')<br>'; # Holiday Check if(in_array(date("d-m-Y", $r), $holidays)) { $r = strtotime("+1 weekday ".date('H:i:s', $r)."", $r); echo '$r is a holiday > move to next workday ('.date("D d-m-Y H:i:s", $r).')<br>'; } } # -- $n ------------------------------------- # if $n is before 9am > move to 9am if($nTyme < "090000") { $n = strtotime("9am", $n); echo '$n is before 9am > move to 9am ('.date("D d-m-Y H:i:s", $n).')<br>'; # elseif $n is after 5pm > move to 5pm } elseif($nTyme > "170000") { $n = strtotime("5pm", $n); echo '$n is after 5pm > move to 5pm ('.date("D d-m-Y H:i:s", $n).')<br>'; } # if $n is a holiday > move to last workday 5pm if(in_array(date("d-m-Y", $n), $holidays)) { $n = strtotime("-1 weekday 5pm", $n); echo '$n is a holiday > move to last workday ('.date("D d-m-Y H:i:s", $n).')<br>'; # Boxing Day Check if(date("d-m", $n) == "26-12" || date("d-m-Y", $n) == "28-12-2015") { $n = strtotime("-1 weekday 5pm", $n); echo '$n is boxing day > move to last workday ('.date("D d-m-Y H:i:s", $n).')<br>'; } } # if $n is a weekend > move to last workday 5pm if(!in_array(date("w", $n), $workdays)) { $n = strtotime("-1 weekday 5pm", $n); echo '$n is a weekend > move to last workday ('.date("D d-m-Y H:i:s", $n).')<br>'; # Holiday Check if(in_array(date("d-m-Y", $n), $holidays)) { $n = strtotime("-1 weekday 5pm", $n); echo '$n is a holiday > move to last workday ('.date("D d-m-Y H:i:s", $n).')<br>'; } } echo '<br>-- OUTPUT<br>'; echo '$r = '.date("D d-m-Y H:i:s", $r).'<br>'; echo '$n = '.date("D d-m-Y H:i:s", $n).'<br>'; echo '<br>-- INPUT DIFFERENCE<br>'; $diff = ($n - $r); echo 'Difference in seconds is '.$diff.'<br>'; # work out hours, mins, secs # if $diff is negative > set to 0 if($diff < 0) { $diff = 0; $h = 0; $m = 0; $s = 0; echo '$diff is negative > set to 0<br>'; } echo '$n - $r = '.($n - $r).'<br>'; $h = (int)($diff / 3600); $m = (int)(($diff - $h*3600) / 60); $s = (int)($diff - $h*3600 - $m*60); echo ''.$h.'h '.$m.'m '.$s.'s<br>'; echo '<br>-- LOOP<br>'; $r12 = strtotime("12pm", $r); $n12 = strtotime("12pm", $n); $daysBetween = ceil(abs($n12 - $r12) / 86400); echo '$daysBetween = '.$daysBetween.'<br>'; if($daysBetween == 0) { // do nothing } elseif ($daysBetween == 1) { echo 'Loop stage: '.date("d-m-Y H:i:s", $r).'<br>'; # if $r is a valid workday and not a holiday if(in_array(date("w", $r), $workdays) && !in_array(date("d-m-Y", $r), $holidays)) { # remove 16 hours $diff-=57600; echo ' > Removed 16 hours (is a valid day) for '.date("d-m-Y H:i:s", $r).'<br>'; } else { # remove 24 hours $diff-=86400; echo ' > Removed 24 hours (isn\'t a valid day) for '.date("d-m-Y H:i:s", $r).'<br>'; } } elseif ($daysBetween >= 2) { for($i=0;$i<$daysBetween;$i++) { echo 'Loop stage: '.date("d-m-Y H:i:s", $r).'<br>'; # if $r is a valid workday and not a holiday if(in_array(date("w", $r), $workdays) && !in_array(date("d-m-Y", $r), $holidays)) { echo ' > Removed 16 hours (is a valid day) for '.date("d-m-Y H:i:s", $r).'<br>'; $diff-=57600; } else { # remove 24 hours $diff-=86400; echo ' > Removed 24 hours (isn\'t a valid day) for '.date("d-m-Y H:i:s", $r).'<br>'; } $r = strtotime("+1 day", $r); } } echo '<br>-- OUTPUT DIFFERENCE<br>'; echo 'Difference in seconds is '.$diff.'<br>'; # work out hours, mins, secs # if $diff is negative > set to 0 if($diff < 0) { $diff = 0; $h = 0; $m = 0; $s = 0; echo '$diff is negative > set to 0<br>'; } echo '$n - $r = '.($n - $r).'<br>'; $h = (int)($diff / 3600); $m = (int)(($diff - $h*3600) / 60); $s = (int)($diff - $h*3600 - $m*60); echo ''.$h.'h '.$m.'m '.$s.'s<br>'; ?> Edited March 25, 2013 by Clarkey Quote Link to comment https://forums.phpfreaks.com/topic/274681-date-time-difference-using-only-working-hours/page/2/#findComment-1420888 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.