php - saber - Diferencia de días sin fines de semana
identificar dias festivos en excel (9)
Quiero contar la diferencia total del día de la entrada del usuario
Por ejemplo, cuando el usuario ingresa
start_date = 2012-09-06
y end-date = 2012-09-11
Por ahora estoy usando este código para encontrar la diferencia
$count = abs(strtotime($start_date) - strtotime($end_date));
$day = $count+86400;
$total = floor($day/(60*60*24));
El resultado del total será 6. Pero el problema es que no quiero incluir los días del fin de semana (sábado y domingo)
2012-09-06
2012-09-07
2012-09-08 Saturday
2012-09-09 Sunday
2012-09-10
2012-09-11
Entonces el resultado será 4
----actualizar---
Tengo una tabla que contiene la fecha, el nombre de la tabla es la fecha de vacaciones
por ejemplo, la tabla contiene 2012-09-07
Por lo tanto, el día total será 3, porque no contó la fecha de vacaciones
¿Cómo hago eso para equiparar la fecha de entrada a la fecha en la tabla?
Muy fácil con mis favoritos: DateTime
, DateInterval
y 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(''Y-m-d''), $holidays)) {
$days--;
}
}
echo $days; // 4
date (''N'') obtiene el día de la semana (1 - lunes, 7 - domingo)
$start = strtotime(''2012-08-06'');
$end = strtotime(''2012-09-06'');
$count = 0;
while(date(''Y-m-d'', $start) < date(''Y-m-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
Aquí hay una alternativa para calcular los días hábiles entre dos fechas y también excluye las vacaciones en EE. UU. Utilizando Date_Holidays de Pear desde http://pear.php.net/package/Date_Holidays .
$ start_date y $ end_date deben ser objetos DateTime (puede usar el new DateTime(''@''.$timestamp)
para convertir de la marca de tiempo al objeto DateTime).
<?php
function business_days($start_date, $end_date)
{
require_once ''Date/Holidays.php'';
$dholidays = &Date_Holidays::factory(''USA'');
$days = 0;
$period = new DatePeriod($start_date, new DateInterval(''P1D''), $end_date);
foreach($period as $dt)
{
$curr = $dt->format(''D'');
if($curr != ''Sat'' && $curr != ''Sun'' && !$dholidays->isHoliday($dt->format(''Y-m-d'')))
{
$days++;
}
}
return $days;
}
?>
Si no necesita días completos sino segundos precisos, pruebe este código. Esto acepta marcas de tiempo unix como entrada.
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;
}
En mi caso, necesitaba la misma respuesta que OP, pero quería algo un poco más pequeño. La respuesta de @ Bojan funcionó, pero no me gustó que no funciona con los objetos DateTime
, requería usar marcas de tiempo, y estaba comparando contra strings
lugar de los propios objetos en sí (que se siente raro) ... Aquí hay una versión revisada de su responder.
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;
}
Comentario de Per @ xzdead si desea que incluya la fecha de inicio y finalización:
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;
}
La forma más fácil y rápida de obtener la diferencia sin fines de semana es mediante el uso de la biblioteca de carbono .
Aquí hay un ejemplo de cómo usarlo:
<?php
$from = Carbon/Carbon::parse(''2016-05-21 22:00:00'');
$to = Carbon/Carbon::parse(''2016-05-21 22:00:00'');
echo $to->diffInWeekdays($from);
/**
* Getting the Weekdays count[ Excludes : Weekends]
*
* @param type $fromDateTimestamp
* @param type $toDateTimestamp
* @return int
*/
public static function getWeekDaysCount($fromDateTimestamp = null, $toDateTimestamp=null) {
$startDateString = date(''Y-m-d'', $fromDateTimestamp);
$timestampTomorrow = strtotime(''+1 day'', $toDateTimestamp);
$endDateString = date("Y-m-d", $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;
}
Eche un vistazo a esta entrada: calcule los días hábiles
(En su caso, podría dejar de lado la parte de ''días festivos'' ya que solo está trabajando / días hábiles)
<?php
//The function returns the no. of business days between two dates
function getWorkingDays($startDate,$endDate){
// do strtotime calculations just once
$endDate = strtotime($endDate);
$startDate = strtotime($startDate);
//The total number of days between the two dates. We compute the no. of seconds and divide it to 60*60*24
//We add one to inlude both dates in the interval.
$days = ($endDate - $startDate) / 86400 + 1;
$no_full_weeks = floor($days / 7);
$no_remaining_days = fmod($days, 7);
//It will return 1 if it''s Monday,.. ,7 for Sunday
$the_first_day_of_week = date("N", $startDate);
$the_last_day_of_week = date("N", $endDate);
//---->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");
?>