Diferença diária sem fins de semana

Eu quero contar a diferença de dia total da input do usuário

Por exemplo, quando as inputs do usuário

start_date = 2012-09-06 e end-date = 2012-09-11

Por enquanto estou usando este código para encontrar a diferença

 $count = abs(strtotime($start_date) - strtotime($end_date)); $day = $count+86400; $total = floor($day/(60*60*24)); 

O resultado do total será 6. Mas o problema é que eu não quero include os dias no fim de semana (sábado e domingo)

 2012-09-06 2012-09-07 2012-09-08 Saturday 2012-09-09 Sunday 2012-09-10 2012-09-11 

Então, o resultado será 4

—-atualizar—

Eu tenho uma tabela que contém data, o nome da tabela é data do feriado

por exemplo, a tabela contém 2012-09-07

Então, o dia total será de 3, porque não conta a data do feriado

Como eu faço isso para equiparar a data da input para a data na tabela?

Muito fácil com meus favoritos: DateTime , DateInterval e DatePeriod

 $start = new DateTime('2012-09-06'); $end = new DateTime('2012-09-11'); // otherwise the end date is excluded (bug?) $end->modify('+1 day'); $interval = $end->diff($start); // total days $days = $interval->days; // create an iterateable period of date (P1D equates to 1 day) $period = new DatePeriod($start, new DateInterval('P1D'), $end); // best stored as array, so you can add more than one $holidays = array('2012-09-07'); foreach($period as $dt) { $curr = $dt->format('D'); // substract if Saturday or Sunday if ($curr == 'Sat' || $curr == 'Sun') { $days--; } // (optional) for the updated question elseif (in_array($dt->format('Ym-d'), $holidays)) { $days--; } } echo $days; // 4 

No meu caso, eu precisava da mesma resposta que OP, mas queria algo um pouco menor. @ A resposta de Bojan funcionou, mas não gostei que não funcionasse com os objects DateTime , exigidos usando timestamps, e estava comparando contra strings vez dos próprios objects reais (o que parece hackeado) … Aqui está uma versão revisada do seu responda.

 function getWeekdayDifference(\DateTime $startDate, \DateTime $endDate) { $days = 0; while($startDate->diff($endDate)->days > 0) { $days += $startDate->format('N') < 6 ? 1 : 0; $startDate = $startDate->add(new \DateInterval("P1D")); } return $days; } 

Per @ xzdead’s comment se você gostaria que isso incluísse a data de início e término:

 function getWeekdayDifference(\DateTime $startDate, \DateTime $endDate) { $isWeekday = function (\DateTime $date) { return $date->format('N') < 6; }; $days = $isWeekday($endDate) ? 1 : 0; while($startDate->diff($endDate)->days > 0) { $days += $isWeekday($startDate) ? 1 : 0; $startDate = $startDate->add(new \DateInterval("P1D")); } return $days; } 

data (‘N’) recebe o dia da semana (1 – segunda-feira, 7 a domingo)

 $start = strtotime('2012-08-06'); $end = strtotime('2012-09-06'); $count = 0; while(date('Ym-d', $start) < date('Ym-d', $end)){ $count += date('N', $start) < 6 ? 1 : 0; $start = strtotime("+1 day", $start); } echo $count; 

use DateTime :

 $datetime1 = new DateTime('2012-09-06'); $datetime2 = new DateTime('2012-09-11'); $interval = $datetime1->diff($datetime2); $woweekends = 0; for($i=0; $i<=$interval->d; $i++){ $modif = $datetime1->modify('+1 day'); $weekday = $datetime1->format('w'); if($weekday != 0 && $weekday != 6){ // 0 for Sunday and 6 for Saturday $woweekends++; } } echo $woweekends." days without weekend"; // 4 days without weekends 

A maneira mais fácil e rápida de fazer diferença sem fins de semana é usando a biblioteca Carbon .

Aqui está um exemplo de como usá-lo:

 diffInWeekdays($from); 

Dê uma olhada nesta publicação: Calcule dias úteis

(No seu caso, você poderia deixar de fora a parte “feriados”, já que você está apenas após o trabalho / dias úteis)

 The two can be equal in leap years when february has 29 days, the equal sign is added here //In the first case the whole interval is within a week, in the second case the interval falls in two weeks. if ($the_first_day_of_week <= $the_last_day_of_week) { if ($the_first_day_of_week <= 6 && 6 <= $the_last_day_of_week) $no_remaining_days--; if ($the_first_day_of_week <= 7 && 7 <= $the_last_day_of_week) $no_remaining_days--; } else { // (edit by Tokes to fix an edge case where the start day was a Sunday // and the end day was NOT a Saturday) // the day of the week for start is later than the day of the week for end if ($the_first_day_of_week == 7) { // if the start date is a Sunday, then we definitely subtract 1 day $no_remaining_days--; if ($the_last_day_of_week == 6) { // if the end date is a Saturday, then we subtract another day $no_remaining_days--; } } else { // the start date was a Saturday (or earlier), and the end date was (Mon..Fri) // so we skip an entire weekend and subtract 2 days $no_remaining_days -= 2; } } //The no. of business days is: (number of weeks between the two dates) * (5 working days) + the remainder //---->february in none leap years gave a remainder of 0 but still calculated weekends between first and last day, this is one way to fix it $workingDays = $no_full_weeks * 5; if ($no_remaining_days > 0 ) { $workingDays += $no_remaining_days; } return $workingDays; } // This will return 4 echo getWorkingDays("2012-09-06","2012-09-11"); ?> 

Se você não precisa de dias completos, mas precisos segundos, tente esse código. Isso aceita timestamps unix como input.

 function timeDifferenceWithoutWeekends($from, $to) { $start = new DateTime("@".$from); $current = clone $start; $end = new DateTime("@".$to); $sum = 0; while ($current<$end) { $endSlice = clone $current; $endSlice->setTime(0,0,0); $endSlice->modify('+1 day'); if ($endSlice>$end) { $endSlice= clone $end; } $seconds = $endSlice->getTimestamp()-$current->getTimestamp(); $currentDay = $current->format("D"); if ($currentDay != 'Sat' && $currentDay != 'Sun') { $sum+=$seconds; } $current = $endSlice; } return $sum; } 
 /** * Getting the Weekdays count[ Excludes : Weekends] * * @param type $fromDateTimestamp * @param type $toDateTimestamp * @return int */ public static function getWeekDaysCount($fromDateTimestamp = null, $toDateTimestamp=null) { $startDateString = date('Ym-d', $fromDateTimestamp); $timestampTomorrow = strtotime('+1 day', $toDateTimestamp); $endDateString = date("Ymd", $timestampTomorrow); $objStartDate = new \DateTime($startDateString); //intialize start date $objEndDate = new \DateTime($endDateString); //initialize end date $interval = new \DateInterval('P1D'); // set the interval as 1 day $dateRange = new \DatePeriod($objStartDate, $interval, $objEndDate); $count = 0; foreach ($dateRange as $eachDate) { if ( $eachDate->format("w") != 6 && $eachDate->format("w") != 0 ) { ++$count; } } return $count; } 

Aqui está uma alternativa para calcular os dias úteis entre duas datas e também exclui os feriados dos EUA usando Date_Holidays Pear’s de http://pear.php.net/package/Date_Holidays .

$ start_date e $ end_date devem ser objects DateTime (você pode usar o new DateTime('@'.$timestamp) para converter do timestamp para o object DateTime).

 format('D'); if($curr != 'Sat' && $curr != 'Sun' && !$dholidays->isHoliday($dt->format('Ym-d'))) { $days++; } } return $days; } ?>