tiene promedio para mes habiles funcion fechas entre dias cuantos como calcular año php calendar date

php - promedio - Calcular días hábiles



dias habiles en un año (30)

A continuación se muestra el código de trabajo para calcular los días hábiles hábiles a partir de una fecha determinada.

<?php $holiday_date_array = array("2016-01-26", "2016-03-07", "2016-03-24", "2016-03-25", "2016-04-15", "2016-08-15", "2016-09-12", "2016-10-11", "2016-10-31"); $date_required = "2016-03-01"; function increase_date($date_required, $holiday_date_array=array(), $days = 15){ if(!empty($date_required)){ $counter_1=0; $incremented_date = ''''; for($i=1; $i <= $days; $i++){ $date = strtotime("+$i day", strtotime($date_required)); $day_name = date("D", $date); $incremented_date = date("Y-m-d", $date); if($day_name==''Sat''||$day_name==''Sun''|| in_array($incremented_date ,$holiday_date_array)==true){ $counter_1+=1; } } if($counter_1 > 0){ return increase_date($incremented_date, $holiday_date_array, $counter_1); }else{ return $incremented_date; } }else{ return ''invalid''; } } echo increase_date($date_required, $holiday_date_array, 15); ?> //output after adding 15 business working days in 2016-03-01 will be "2016-03-23"

Necesito un método para agregar "días hábiles" en PHP. Por ejemplo, viernes 12/5 + 3 días hábiles = miércoles 12/10.

Como mínimo, necesito el código para entender los fines de semana, pero lo ideal sería que también tenga en cuenta las vacaciones federales de EE. UU. Estoy seguro de que podría llegar a una solución por la fuerza bruta si es necesario, pero espero que haya un enfoque más elegante. ¿Nadie?

Gracias.


Acabo de crear esta función, que parece funcionar muy bien:

function getBusinessDays($date1, $date2){ if(!is_numeric($date1)){ $date1 = strtotime($date1); } if(!is_numeric($date2)){ $date2 = strtotime($date2); } if($date2 < $date1){ $temp_date = $date1; $date1 = $date2; $date2 = $temp_date; unset($temp_date); } $diff = $date2 - $date1; $days_diff = intval($diff / (3600 * 24)); $current_day_of_week = intval(date("N", $date1)); $business_days = 0; for($i = 1; $i <= $days_diff; $i++){ if(!in_array($current_day_of_week, array("Sunday" => 1, "Saturday" => 7))){ $business_days++; } $current_day_of_week++; if($current_day_of_week > 7){ $current_day_of_week = 1; } } return $business_days; } echo "Business days: " . getBusinessDays("8/15/2014", "8/8/2014");


Acabo de escribir una API que se puede usar para manipular los días hábiles (ninguna de estas soluciones funcionó para mi situación :-); vinculándolo aquí en caso de que alguien más lo encuentre útil.

~ Nate

Clase PHP para calcular días hábiles


Acabo de hacer funcionar mi función en base al código de Bobbin y mcgrailm, agregando algunas cosas que me funcionaron perfectamente.

function add_business_days($startdate,$buisnessdays,$holidays,$dateformat){ $enddate = strtotime($startdate); $day = date(''N'',$enddate); while($buisnessdays > 0){ // compatible with 1 businessday if I''ll need it $enddate = strtotime(date(''Y-m-d'',$enddate).'' +1 day''); $day = date(''N'',$enddate); if($day < 6 && !in_array(date(''Y-m-d'',$enddate),$holidays))$buisnessdays--; } return date($dateformat,$enddate); } // as a parameter in in_array function we should use endate formated to // compare correctly with the holidays array.


Add_business_days tiene un pequeño error. Pruebe lo siguiente con la función existente y la salida será un sábado.

Fecha de inicio = viernes Días hábiles para agregar = 1 Arreglo de días festivos = Agregar fecha para el siguiente lunes.

Lo he arreglado en mi función a continuación.

function add_business_days($startdate, $buisnessdays, $holidays = array(), $dateformat = ''Y-m-d''){ $i= 1; $dayx= strtotime($startdate); $buisnessdays= ceil($buisnessdays); while($i < $buisnessdays) { $day= date(''N'',$dayx); $date= date(''Y-m-d'',$dayx); if($day < 6 && !in_array($date,$holidays)) $i++; $dayx= strtotime($date.'' +1 day''); } ## If the calculated day falls on a weekend or is a holiday, then add days to the next business day $day= date(''N'',$dayx); $date= date(''Y-m-d'',$dayx); while($day >= 6 || in_array($date,$holidays)) { $dayx= strtotime($date.'' +1 day''); $day= date(''N'',$dayx); $date= date(''Y-m-d'',$dayx); } return date($dateformat, $dayx);}


Aquí hay otra solución sin ciclo para cada día.

$from = new DateTime($first_date); $to = new DateTime($second_date); $to->modify(''+1 day''); $interval = $from->diff($to); $days = $interval->format(''%a''); $extra_days = fmod($days, 7); $workdays = ( ( $days - $extra_days ) / 7 ) * 5; $first_day = date(''N'', strtotime($first_date)); $last_day = date(''N'', strtotime("1 day", strtotime($second_date))); $extra = 0; if($first_day > $last_day) { if($first_day == 7) { $first_day = 6; } $extra = (6 - $first_day) + ($last_day - 1); if($extra < 0) { $extra = $extra * -1; } } if($last_day > $first_day) { $extra = $last_day - $first_day; } $days = $workdays + $extra


Aquí hay una función de los comentarios del usuario en la página de función de fecha () en el manual de PHP. Es una mejora de una función anterior en los comentarios que agrega soporte para los años bisiestos.

Ingrese las fechas de inicio y finalización, junto con una matriz de vacaciones que puedan estar en el medio, y devuelve los días hábiles como un número entero:

<?php //The function returns the no. of business days between two dates and it skips the holidays function getWorkingDays($startDate,$endDate,$holidays){ // 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; } //We subtract the holidays foreach($holidays as $holiday){ $time_stamp=strtotime($holiday); //If the holiday doesn''t fall in weekend if ($startDate <= $time_stamp && $time_stamp <= $endDate && date("N",$time_stamp) != 6 && date("N",$time_stamp) != 7) $workingDays--; } return $workingDays; } //Example: $holidays=array("2008-12-25","2008-12-26","2009-01-01"); echo getWorkingDays("2008-12-22","2009-01-02",$holidays) // => will return 7 ?>


Aquí hay una función para agregar días hábiles a una fecha

function add_business_days($startdate,$buisnessdays,$holidays,$dateformat){ $i=1; $dayx = strtotime($startdate); while($i < $buisnessdays){ $day = date(''N'',$dayx); $date = date(''Y-m-d'',$dayx); if($day < 6 && !in_array($date,$holidays))$i++; $dayx = strtotime($date.'' +1 day''); } return date($dateformat,$dayx); } //Example date_default_timezone_set(''Europe/London''); $startdate = ''2012-01-08''; $holidays=array("2012-01-10"); echo ''<p>Start date: ''.date(''r'',strtotime( $startdate)); echo ''<p>''.add_business_days($startdate,7,$holidays,''r'');

Otra publicación menciona getWorkingDays (de los comentarios de php.net e incluida aquí), pero creo que se rompe si comienzas un domingo y terminas en un día de trabajo.

Usando lo siguiente (deberá incluir la función getWorkingDays de la publicación anterior)

date_default_timezone_set(''Europe/London''); //Example: $holidays = array(''2012-01-10''); $startDate = ''2012-01-08''; $endDate = ''2012-01-13''; echo getWorkingDays( $startDate,$endDate,$holidays);

Da el resultado como 5 no 4

Sun, 08 Jan 2012 00:00:00 +0000 weekend Mon, 09 Jan 2012 00:00:00 +0000 Tue, 10 Jan 2012 00:00:00 +0000 holiday Wed, 11 Jan 2012 00:00:00 +0000 Thu, 12 Jan 2012 00:00:00 +0000 Fri, 13 Jan 2012 00:00:00 +0000

La siguiente función se utilizó para generar lo anterior.

function get_working_days($startDate,$endDate,$holidays){ $debug = true; $work = 0; $nowork = 0; $dayx = strtotime($startDate); $endx = strtotime($endDate); if($debug){ echo ''<h1>get_working_days</h1>''; echo ''startDate: ''.date(''r'',strtotime( $startDate)).''<br>''; echo ''endDate: ''.date(''r'',strtotime( $endDate)).''<br>''; var_dump($holidays); echo ''<p>Go to work...''; } while($dayx <= $endx){ $day = date(''N'',$dayx); $date = date(''Y-m-d'',$dayx); if($debug)echo ''<br />''.date(''r'',$dayx).'' ''; if($day > 5 || in_array($date,$holidays)){ $nowork++; if($debug){ if($day > 5)echo ''weekend''; else echo ''holiday''; } } else $work++; $dayx = strtotime($date.'' +1 day''); } if($debug){ echo ''<p>No work: ''.$nowork.''<br>''; echo ''Work: ''.$work.''<br>''; echo ''Work + no work: ''.($nowork+$work).''<br>''; echo ''All seconds / seconds in a day: ''.floatval(strtotime($endDate)-strtotime($startDate))/floatval(24*60*60); } return $work; } date_default_timezone_set(''Europe/London''); //Example: $holidays=array("2012-01-10"); $startDate = ''2012-01-08''; $endDate = ''2012-01-13''; //broken echo getWorkingDays( $startDate,$endDate,$holidays); //works echo get_working_days( $startDate,$endDate,$holidays);

Trae las vacaciones ...


Aquí hay una solución recursiva. Se puede modificar fácilmente para realizar un seguimiento y devolver la fecha más reciente.

// Returns a $numBusDays-sized array of all business dates, // starting from and including $currentDate. // Any date in $holidays will be skipped over. function getWorkingDays($currentDate, $numBusDays, $holidays = array(), $resultDates = array()) { // exit when we have collected the required number of business days if ($numBusDays === 0) { return $resultDates; } // add current date to return array, if not a weekend or holiday $date = date("w", strtotime($currentDate)); if ( $date != 0 && $date != 6 && !in_array($currentDate, $holidays) ) { $resultDates[] = $currentDate; $numBusDays -= 1; } // set up the next date to test $currentDate = new DateTime("$currentDate + 1 day"); $currentDate = $currentDate->format(''Y-m-d''); return getWorkingDays($currentDate, $numBusDays, $holidays, $resultDates); } // test $days = getWorkingDays(''2008-12-05'', 4); print_r($days);


El cálculo de vacaciones no es estándar en cada estado. Estoy escribiendo una aplicación bancaria para la que necesito algunas reglas comerciales duras, pero aún puedo obtener un estándar aproximado.

/** * National American Holidays * @param string $year * @return array */ public static function getNationalAmericanHolidays($year) { // January 1 - New Year’s Day (Observed) // Calc Last Monday in May - Memorial Day strtotime("last Monday of May 2011"); // July 4 Independence Day // First monday in september - Labor Day strtotime("first Monday of September 2011") // November 11 - Veterans’ Day (Observed) // Fourth Thursday in November Thanksgiving strtotime("fourth Thursday of November 2011"); // December 25 - Christmas Day $bankHolidays = array( $year . "-01-01" // New Years , "". date("Y-m-d",strtotime("last Monday of May " . $year) ) // Memorial Day , $year . "-07-04" // Independence Day (corrected) , "". date("Y-m-d",strtotime("first Monday of September " . $year) ) // Labor Day , $year . "-11-11" // Veterans Day , "". date("Y-m-d",strtotime("fourth Thursday of November " . $year) ) // Thanksgiving , $year . "-12-25" // XMAS ); return $bankHolidays; }


Gracias a Bobbin, mcgrailm, Tony, James Pasta y algunos otros que publicaron aquí. Había escrito mi propia función para agregar días hábiles a una fecha, pero la modifiqué con algún código que encontré aquí. Esto controlará la fecha de inicio de un fin de semana / día festivo. Esto también manejará el horario comercial. Agregué algunos comentarios y dividí el código para que sea más fácil de leer.

<?php function count_business_days($date, $days, $holidays) { $date = strtotime($date); for ($i = 1; $i <= intval($days); $i++) { //Loops each day count //First, find the next available weekday because this might be a weekend/holiday while (date(''N'', $date) >= 6 || in_array(date(''Y-m-d'', $date), $holidays)){ $date = strtotime(date(''Y-m-d'',$date).'' +1 day''); } //Now that we know we have a business day, add 1 day to it $date = strtotime(date(''Y-m-d'',$date).'' +1 day''); //If this day that was previously added falls on a weekend/holiday, then find the next business day while (date(''N'', $date) >= 6 || in_array(date(''Y-m-d'', $date), $holidays)){ $date = strtotime(date(''Y-m-d'',$date).'' +1 day''); } } return date(''Y-m-d'', $date); } //Also add in the code from Tony and James Pasta to handle holidays... function getNationalAmericanHolidays($year) { $bankHolidays = array( ''New Years Day'' => $year . "-01-01", ''Martin Luther King Jr Birthday'' => "". date("Y-m-d",strtotime("third Monday of January " . $year) ), ''Washingtons Birthday'' => "". date("Y-m-d",strtotime("third Monday of February " . $year) ), ''Memorial Day'' => "". date("Y-m-d",strtotime("last Monday of May " . $year) ), ''Independance Day'' => $year . "-07-04", ''Labor Day'' => "". date("Y-m-d",strtotime("first Monday of September " . $year) ), ''Columbus Day'' => "". date("Y-m-d",strtotime("second Monday of October " . $year) ), ''Veterans Day'' => $year . "-11-11", ''Thanksgiving Day'' => "". date("Y-m-d",strtotime("fourth Thursday of November " . $year) ), ''Christmas Day'' => $year . "-12-25" ); return $bankHolidays; } //Now to call it... since we''re working with business days, we should //also be working with business hours so check if it''s after 5 PM //and go to the next day if necessary. //Go to next day if after 5 pm (5 pm = 17) if (date(G) >= 17) { $start_date = date("Y-m-d", strtotime("+ 1 day")); //Tomorrow } else { $start_date = date("Y-m-d"); //Today } //Get the holidays for the current year and also for the next year $this_year = getNationalAmericanHolidays(date(''Y'')); $next_year = getNationalAmericanHolidays(date(''Y'', strtotime("+12 months"))); $holidays = array_merge($this_year, $next_year); //The number of days to count $days_count = 10; echo count_business_days($start_date, $days_count, $holidays); ?>


Hay algunos argumentos para la función de date() que deberían ayudar. Si marca la fecha ("w"), le dará un número para el día de la semana, de 0 para el domingo a 6 para el sábado. Entonces ... tal vez algo como ...

$busDays = 3; $day = date("w"); if( $day > 2 && $day <= 5 ) { /* if between Wed and Fri */ $day += 2; /* add 2 more days for weekend */ } $day += $busDays;

Este es solo un ejemplo aproximado de una posibilidad ...


Intento brutal de detectar el horario laboral - de lunes a viernes de 8 a.m. a 4 p.m.

if (date(''N'')<6 && date(''G'')>8 && date(''G'')<16) { // we have a working time (or check for holidays) }


Mi versión basada en el trabajo de @mcgrailm ... modificó porque el informe debía revisarse dentro de 3 días hábiles, y si se enviaba un fin de semana, el recuento comenzaría el lunes siguiente:

function business_days_add($start_date, $business_days, $holidays = array()) { $current_date = strtotime($start_date); $business_days = intval($business_days); // Decrement does not work on strings while ($business_days > 0) { if (date(''N'', $current_date) < 6 && !in_array(date(''Y-m-d'', $current_date), $holidays)) { $business_days--; } if ($business_days > 0) { $current_date = strtotime(''+1 day'', $current_date); } } return $current_date; }

Y resolviendo la diferencia de dos fechas en términos de días hábiles:

function business_days_diff($start_date, $end_date, $holidays = array()) { $business_days = 0; $current_date = strtotime($start_date); $end_date = strtotime($end_date); while ($current_date <= $end_date) { if (date(''N'', $current_date) < 6 && !in_array(date(''Y-m-d'', $current_date), $holidays)) { $business_days++; } if ($current_date <= $end_date) { $current_date = strtotime(''+1 day'', $current_date); } } return $business_days; }

Como nota, todos los que usan 86400 o 24 * 60 * 60, por favor no ... su tiempo de olvido cambia de invierno / verano, donde un día no exactamente 24 horas. Si bien es un poco más lento el strtotime (''+ 1 day'', $ timestamp), es mucho más confiable.


Obtenga el número de días hábiles sin vacaciones entre dos fechas:

Use el ejemplo:

echo number_of_working_days(''2013-12-23'', ''2013-12-29'');

Salida:

3

Función:

function number_of_working_days($from, $to) { $workingDays = [1, 2, 3, 4, 5]; # date format = N (1 = Monday, ...) $holidayDays = [''*-12-25'', ''*-01-01'', ''2013-12-23'']; # variable and fixed holidays $from = new DateTime($from); $to = new DateTime($to); $to->modify(''+1 day''); $interval = new DateInterval(''P1D''); $periods = new DatePeriod($from, $interval, $to); $days = 0; foreach ($periods as $period) { if (!in_array($period->format(''N''), $workingDays)) continue; if (in_array($period->format(''Y-m-d''), $holidayDays)) continue; if (in_array($period->format(''*-m-d''), $holidayDays)) continue; $days++; } return $days; }


Para las vacaciones, haga una serie de días en algún formato que date () pueda producir. Ejemplo:

// I know, these aren''t holidays $holidays = array( ''Jan 2'', ''Feb 3'', ''Mar 5'', ''Apr 7'', // ... );

Luego use las in_array() y date() para verificar si la marca de tiempo representa un día festivo:

$day_of_year = date(''M j'', $timestamp); $is_holiday = in_array($day_of_year, $holidays);


Personalmente, creo que esta es una solución más limpia y concisa:

function onlyWorkDays( $d ) { $holidays = array(''2013-12-25'',''2013-12-31'',''2014-01-01'',''2014-01-20'',''2014-02-17'',''2014-05-26'',''2014-07-04'',''2014-09-01'',''2014-10-13'',''2014-11-11'',''2014-11-27'',''2014-12-25'',''2014-12-31''); while (in_array($d->format("Y-m-d"), $holidays)) { // HOLIDAYS $d->sub(new DateInterval("P1D")); } if ($d->format("w") == 6) { // SATURDAY $d->sub(new DateInterval("P1D")); } if ($d->format("w") == 0) { // SUNDAY $d->sub(new DateInterval("P2D")); } return $d; }

Simplemente envíe la new fecha propuesta a esta función.


Puedes probar esta función que es más simple.

function getWorkingDays($startDate, $endDate) { $begin = strtotime($startDate); $end = strtotime($endDate); if ($begin > $end) { return 0; } else { $no_days = 0; while ($begin <= $end) { $what_day = date("N", $begin); if (!in_array($what_day, [6,7]) ) // 6 and 7 are weekend $no_days++; $begin += 86400; // +1 day }; return $no_days; } }


Tenía la misma necesidad que comencé con el primer ejemplo de bobina y terminé con esto

function add_business_days($startdate,$buisnessdays,$holidays=array(),$dateformat){ $enddate = strtotime($startdate); $day = date(''N'',$enddate); while($buisnessdays > 1){ $enddate = strtotime(date(''Y-m-d'',$enddate).'' +1 day''); $day = date(''N'',$enddate); if($day < 6 && !in_array($enddate,$holidays))$buisnessdays--; } return date($dateformat,$enddate); }

hth alguien


Una función para agregar o restar días hábiles a partir de una fecha determinada, esto no cuenta para las vacaciones.

function dateFromBusinessDays($days, $dateTime=null) { $dateTime = is_null($dateTime) ? time() : $dateTime; $_day = 0; $_direction = $days == 0 ? 0 : intval($days/abs($days)); $_day_value = (60 * 60 * 24); while($_day !== $days) { $dateTime += $_direction * $_day_value; $_day_w = date("w", $dateTime); if ($_day_w > 0 && $_day_w < 6) { $_day += $_direction * 1; } } return $dateTime; }

usar como tal ...

echo date("m/d/Y", dateFromBusinessDays(-7)); echo date("m/d/Y", dateFromBusinessDays(3, time() + 3*60*60*24));


Una mejora de la función ofrecida por James Pasta arriba, para incluir todas las Fiestas Federales, y corregir el 4 de julio (se calculó como el 4 de junio anterior), y también incluir el nombre de la fiesta como la tecla de matriz ...

/ **
* Fiestas Nacionales Americanas
* @param string $ year
* @return array
* /
función estática pública getNationalAmericanHolidays ($ year) {

// January 1 - New Year''s Day (Observed) // Third Monday in January - Birthday of Martin Luther King, Jr. // Third Monday in February - Washington’s Birthday / President''s Day // Last Monday in May - Memorial Day // July 4 - Independence Day // First Monday in September - Labor Day // Second Monday in October - Columbus Day // November 11 - Veterans’ Day (Observed) // Fourth Thursday in November Thanksgiving Day // December 25 - Christmas Day $bankHolidays = array( [''New Years Day''] => $year . "-01-01", [''Martin Luther King Jr Birthday''] => "". date("Y-m-d",strtotime("third Monday of January " . $year) ), [''Washingtons Birthday''] => "". date("Y-m-d",strtotime("third Monday of February " . $year) ), [''Memorial Day''] => "". date("Y-m-d",strtotime("last Monday of May " . $year) ), [''Independance Day''] => $year . "-07-04", [''Labor Day''] => "". date("Y-m-d",strtotime("first Monday of September " . $year) ), [''Columbus Day''] => "". date("Y-m-d",strtotime("second Monday of October " . $year) ), [''Veterans Day''] => $year . "-11-11", [''Thanksgiving Day''] => "". date("Y-m-d",strtotime("fourth Thursday of November " . $year) ), [''Christmas Day''] => $year . "-12-25" ); return $bankHolidays;

}


Variante 1:

<?php /* * Does not count current day, the date returned is the last business day * Requires PHP 5.1 (Using ISO-8601 week) */ function businessDays($timestamp = false, $bDays = 2) { if($timestamp === false) $timestamp = time(); while ($bDays>0) { $timestamp += 86400; if (date(''N'', $timestamp)<6) $bDays--; } return $timestamp; }

Variante 2:

<?php /* * Does not count current day, the date returned is a business day * following the last business day * Requires PHP 5.1 (Using ISO-8601 week) */ function businessDays($timestamp = false, $bDays = 2) { if($timestamp === false) $timestamp = time(); while ($bDays+1>0) { $timestamp += 86400; if (date(''N'', $timestamp)<6) $bDays--; } return $timestamp; }

Variante 3:

<?php /* * Does not count current day, the date returned is * a date following the last business day (can be weekend or not. * See above for alternatives) * Requires PHP 5.1 (Using ISO-8601 week) */ function businessDays($timestamp = false, $bDays = 2) { if($timestamp === false) $timestamp = time(); while ($bDays>0) { $timestamp += 86400; if (date(''N'', $timestamp)<6) $bDays--; } return $timestamp += 86400; }

Las consideraciones adicionales de vacaciones se pueden hacer usando variaciones de lo anterior haciendo lo siguiente. ¡Nota! asegúrese de que todas las marcas de tiempo sean a la misma hora del día (es decir, a la medianoche).

Haga una serie de fechas de vacaciones (como unixtimestamps), es decir:

$holidays = array_flip(strtotime(''2011-01-01''),strtotime(''2011-12-25''));

Modificar línea:

if (date(''N'', $timestamp)<6) $bDays--;

ser :

if (date(''N'', $timestamp)<6 && !isset($holidays[$timestamp])) $bDays--;

¡Hecho!

<?php /* * Does not count current day, the date returned is the last business day * Requires PHP 5.1 (Using ISO-8601 week) */ function businessDays($timestamp = false, $bDays = 2) { if($timestamp === false) $timestamp = strtotime(date(''Y-m-d'',time())); $holidays = array_flip(strtotime(''2011-01-01''),strtotime(''2011-12-25'')); while ($bDays>0) { $timestamp += 86400; if (date(''N'', $timestamp)<6 && !isset($holidays[$timestamp])) $bDays--; } return $timestamp; }


function get_business_days_forward_from_date ($ num_days, $ start_date = '''', $ rtn_fmt = ''Ym-d'') {

// $start_date will default to today if ($start_date=='''') { $start_date = date("Y-m-d"); } $business_day_ct = 0; $max_days = 10000 + $num_days; // to avoid any possibility of an infinite loop // define holidays, this currently only goes to 2012 because, well, you know... ;-) // if the world is still here after that, you can find more at // http://www.opm.gov/Operating_Status_Schedules/fedhol/2013.asp // always add holidays in order, because the iteration will stop when the holiday is > date being tested $fed_holidays=array( "2010-01-01", "2010-01-18", "2010-02-15", "2010-05-31", "2010-07-05", "2010-09-06", "2010-10-11", "2010-11-11", "2010-11-25", "2010-12-24", "2010-12-31", "2011-01-17", "2011-02-21", "2011-05-30", "2011-07-04", "2011-09-05", "2011-10-10", "2011-11-11", "2011-11-24", "2011-12-26", "2012-01-02", "2012-01-16", "2012-02-20", "2012-05-28", "2012-07-04", "2012-09-03", "2012-10-08", "2012-11-12", "2012-11-22", "2012-12-25", ); $curr_date_ymd = date(''Y-m-d'', strtotime($start_date)); for ($x=1;$x<$max_days;$x++) { if (intval($num_days)==intval($business_day_ct)) { return(date($rtn_fmt, strtotime($curr_date_ymd))); } // date found - return // get next day to check $curr_date_ymd = date(''Y-m-d'', (strtotime($start_date)+($x * 86400))); // add 1 day to the current date $is_business_day = 1; // check if this is a weekend 1 (for Monday) through 7 (for Sunday) if ( intval(date("N",strtotime($curr_date_ymd))) > 5) { $is_business_day = 0; } //check for holiday foreach($fed_holidays as $holiday) { if (strtotime($holiday)==strtotime($curr_date_ymd)) // holiday found { $is_business_day = 0; break 1; } if (strtotime($holiday)>strtotime($curr_date_ymd)) { break 1; } // past date, stop searching (always add holidays in order) } $business_day_ct = $business_day_ct + $is_business_day; // increment if this is a business day } // if we get here, you are hosed return ("ERROR");

}


calculate workdays between two dates including holidays and custom workweek

The answer is not that trivial - thus my suggestion would be to use a class where you can configure more than relying on simplistic function (or assuming a fixed locale and culture). To get the date after a certain number of workdays you''ll:

  1. need to specify what weekdays you''ll be working (default to MON-FRI) - the class allows you to enable or disable each weekday individually.
  2. need to know that you need to consider public holidays (country and state) to be accurate

Enfoque funcional

/** * @param days, int * @param $format, string: dateformat (if format defined OTHERWISE int: timestamp) * @param start, int: timestamp (mktime) default: time() //now * @param $wk, bit[]: flags for each workday (0=SUN, 6=SAT) 1=workday, 0=day off * @param $holiday, string[]: list of dates, YYYY-MM-DD, MM-DD */ function working_days($days, $format='''', $start=null, $week=[0,1,1,1,1,1,0], $holiday=[]) { if(is_null($start)) $start = time(); if($days <= 0) return $start; if(count($week) != 7) trigger_error(''workweek must contain bit-flags for 7 days''); if(array_sum($week) == 0) trigger_error(''workweek must contain at least one workday''); $wd = date(''w'', $start);//0=sun, 6=sat $time = $start; while($days) { if( $week[$wd] && !in_array(date(''Y-m-d'', $time), $holiday) && !in_array(date(''m-d'', $time), $holiday) ) --$days; //decrement on workdays $wd = date(''w'', $time += 86400); //add one day in seconds } $time -= 86400;//include today return $format ? date($format, $time): $time; } //simple usage $ten_days = working_days(10, ''D F d Y''); echo ''<br>ten workingdays (MON-FRI) disregarding holidays: '',$ten_days; //work on saturdays and add new years day as holiday $ten_days = working_days(10, ''D F d Y'', null, [0,1,1,1,1,1,1], [''01-01'']); echo ''<br>ten workingdays (MON-SAT) disregarding holidays: '',$ten_days;


Esta es otra solución, es casi un 25% más rápida que verificar las vacaciones con in_array:

/** * Function to calculate the working days between two days, considering holidays. * @param string $startDate -- Start date of the range (included), formatted as Y-m-d. * @param string $endDate -- End date of the range (included), formatted as Y-m-d. * @param array(string) $holidayDates -- OPTIONAL. Array of holidays dates, formatted as Y-m-d. (e.g. array("2016-08-15", "2016-12-25")) * @return int -- Number of working days. */ function getWorkingDays($startDate, $endDate, $holidayDates=array()){ $dateRange = new DatePeriod(new DateTime($startDate), new DateInterval(''P1D''), (new DateTime($endDate))->modify("+1day")); foreach ($dateRange as $dr) { if($dr->format("N")<6){$workingDays[]=$dr->format("Y-m-d");} } return count(array_diff($workingDays, $holidayDates)); }


PHPClasses have a nice class for this named PHP Working Days . You can check this class.


$startDate = new DateTime( ''2013-04-01'' ); //intialize start date $endDate = new DateTime( ''2013-04-30'' ); //initialize end date $holiday = array(''2013-04-11'',''2013-04-25''); //this is assumed list of holiday $interval = new DateInterval(''P1D''); // set the interval as 1 day $daterange = new DatePeriod($startDate, $interval ,$endDate); foreach($daterange as $date){ if($date->format("N") <6 AND !in_array($date->format("Y-m-d"),$holiday)) $result[] = $date->format("Y-m-d"); } echo "<pre>";print_r($result);


<?php // $today is the UNIX timestamp for today''s date $today = time(); echo "<strong>Today is (ORDER DATE): " . ''<font color="red">'' . date(''l, F j, Y'', $today) . "</font></strong><br/><br/>"; //The numerical representation for day of week (Ex. 01 for Monday .... 07 for Sunday $today_numerical = date("N",$today); //leadtime_days holds the numeric value for the number of business days $leadtime_days = $_POST["leadtime"]; //leadtime is the adjusted date for shipdate $shipdate = time(); while ($leadtime_days > 0) { if ($today_numerical != 5 && $today_numerical != 6) { $shipdate = $shipdate + (60*60*24); $today_numerical = date("N",$shipdate); $leadtime_days --; } else $shipdate = $shipdate + (60*60*24); $today_numerical = date("N",$shipdate); } echo ''<strong>Estimated Ship date: '' . ''<font color="green">'' . date(''l, F j, Y'', $shipdate) . "</font></strong>"; ?>


<?php function AddWorkDays(){ $i = 0; $d = 5; // Number of days to add while($i <= $d) { $i++; if(date(''N'', mktime(0, 0, 0, date(m), date(d)+$i, date(Y))) < 5) { $d++; } } return date(Y).'',''.date(m).'',''.(date(d)+$d); } ?>


date_default_timezone_set(''America/New_York''); /** Given a number days out, what day is that when counting by ''business'' days * get the next business day. by default it looks for next business day * ie calling $date = get_next_busines_day(); on monday will return tuesday * $date = get_next_busines_day(2); on monday will return wednesday * $date = get_next_busines_day(2); on friday will return tuesday * * @param $number_of_business_days (integer) how many business days out do you want * @param $start_date (string) strtotime parseable time value * @param $ignore_holidays (boolean) true/false to ignore holidays * @param $return_format (string) as specified in php.net/date */ function get_next_business_day($number_of_business_days=1,$start_date=''today'',$ignore_holidays=false,$return_format=''m/d/y'') { // get the start date as a string to time $result = strtotime($start_date); // now keep adding to today''s date until number of business days is 0 and we land on a business day while ($number_of_business_days > 0) { // add one day to the start date $result = strtotime(date(''Y-m-d'',$result) . " + 1 day"); // this day counts if it''s a weekend and not a holiday, or if we choose to ignore holidays if (is_weekday(date(''Y-m-d'',$result)) && (!(is_holiday(date(''Y-m-d'',$result))) || $ignore_holidays) ) $number_of_business_days--; } // when my $number of business days is exausted I have my final date return(date($return_format,$result)); } function is_weekend($date) { // return if this is a weekend date or not. return (date(''N'', strtotime($date)) >= 6); } function is_weekday($date) { // return if this is a weekend date or not. return (date(''N'', strtotime($date)) < 6); } function is_holiday($date) { // return if this is a holiday or not. // what are my holidays for this year $holidays = array("New Year''s Day 2011" => "12/31/10", "Good Friday" => "04/06/12", "Memorial Day" => "05/28/12", "Independence Day" => "07/04/12", "Floating Holiday" => "12/31/12", "Labor Day" => "09/03/12", "Thanksgiving Day" => "11/22/12", "Day After Thanksgiving Day" => "11/23/12", "Christmas Eve" => "12/24/12", "Christmas Day" => "12/25/12", "New Year''s Day 2012" => "01/02/12", "New Year''s Day 2013" => "01/01/13" ); return(in_array(date(''m/d/y'', strtotime($date)),$holidays)); } print get_next_business_day(1) . "/n";