Liczba dni roboczych

Liczenie ile minęło dni między jedną datą a drugą to dość częsty "problem" piszących w php. Samo policzenie dni bez rozróżniania na dni robocze jest banalnie proste:

<?php
echo (strtotime('2005-03-30 GMT')-strtotime('2005-03-01 GMT'))/86400;
?>

Jednak wyliczenie dni roboczych to już większa sprawa. By ułatwić sobie i Wam życie, napisałem funkcję, która wylicza liczbę dni roboczych. Pierwotnie funkcja nie uwzględniała świąt ruchomych jednak użytkownik kajko84 dopisał do tego i święta ruchome. Ja to trochę zoptymalizowałem i mamy w pełni funkcjonalną funkcję do wyliczania liczby roboczych.

Kod funkcji

<?php
function workDays($date1, $date2, $withStartDay = false) { 
    $date1=strtotime($date1); 
    $date2=strtotime($date2); 
    if ($date2===$date1 && !$withStartDay) return 0; 
    $char=1; 
    if ($date1>$date2) 
        {$datePom=$date1;$date1=$date2;$date2=$datePom;$char=-1;} 
    $count=0; 
    if (!$withStartDay) 
        $date1=strtotime('+1 day',$date1); 
    $date2=strtotime('+1 day',$date2); 
    $lastYear = null; 
    $hol=array('01-01','05-01','05-03','08-15','11-01','11-11','12-25','12-26'); 
    while ($date1<$date2) { 
        $year = date('Y', $date1); 
        if ($year !== $lastYear){ 
            $lastYear = $year; 
            $easter = date('m-d', easter_date($year)); 
            $date = strtotime($year . '-' . $easter); 
            $easterSec = date('m-d', strtotime('+1 day', $date)); 
            $cc = date('m-d', strtotime('+60 days', $date)); 
            $hol[8] = $easter; 
            $hol[9] = $easterSec; 
            $hol[10] = $cc; 
        } 
        $weekDay=date('w',$date1); 
		$md = date('m-d',$date1);
        if (!($weekDay==0 || $weekDay==6 || in_array($md,$hol) || $year>2010 && $md=='01-06')) {
			$count++; 
		}
        $date1=strtotime('+1 day',$date1); 
    } 
    $count*=$char; 
    return $count; 
}
?>
,gdzie:
  • $date1 - data początkowa w formacie rrrr-mm-dd
  • $date2 - data końcowa w formacie rrrr-mm-dd
  • $withStartDay - określa czy liczyć liczbę dni wraz z dniem początkowym. Domyślnie liczone jest bez tegoż dnia.

W przypadku, gdy data początkowo będzie większa od daty końcowej, dostaniemy wynik ujemny.

Użycie

Użycie funkcji jest banalnie proste:

<?php
echo workDays('2007-10-10','2007-10-12'); //wyświetli 2
echo workDays('2007-10-10','2007-10-14'); //wyświetli 2, gdyż dwa ostanie dni to weekend
echo workDays('2007-10-12','2007-10-10'); //wyświetli -2
echo workDays('2007-10-10','2007-10-12',true);//wyświetli 3, gdyż liczymy z dniem początkowym
?>

Edit:
Na forum php pojawił się kod, który wylicza datę od danej po minięciu określonej liczby dni.

Komentarze

 

2009-01-05 23:47 gość_szakal_kp

Bardzo fajny ten przykład, ale do moich potrzeb niestety wymaga jeszcze dopracowania, nie uwzględnia on przypadku kiedy święto jest dniem wolnym od pracy(sobotą, niedzielą). Ustawodawca mówi że w takim przypadku pracodawca musi pracownikowi taki dzień "oddać". Przykład 3 maj 2008 (sobota).

sprostowanie i rozwiązanie Wyłącznie sobót, jeśli święto wypada w niedziele to nic z tym nie robimy.
A oto rozwiązanie:
<?php
if ((in_array(date('m-d',$date1),$hol) && $weekDay==6))   
    $count--;
?>

Mam nadzieję że komuś się przyda

2009-01-06 07:04 nospor

@szakal_kp dzięki za drobną, aczkolwiek ważną poprawkę
Aczkolwiek nie jestem pewien czy można tak to poprawić. Rozumiem, iż sobotę należy "oddać" ale kto powiedział, że należy oddać akurat w zadanym przez Ciebie okresie czasu, który sprawdzasz. A noż sobota zostanie "oddana" po tym okresie. Wówczas liczba dni roboczych dla okresu, który wyliczasz nie powinna być zmniejszana o jeden dzień.

Wydaje mi się, iż poprawkę należy mieć na uwadze, ale stosować ją należy wg. własnych potrzeb.

2009-01-06 17:39 gość_szakal_kp

Nospor, bardzo trafna uwaga. Jeszcze nikt nie stworzył algorytmu obliczającego kiedy pracownik odbiera sobie zaległe wolne Mi jest ten algorytm potrzebny do obliczania wymiaru czasu pracy w danym miesiącu w programie płacowym.

2009-01-16 13:43 gość_froggy

Zgodnie z ustawa, mamy obecnie 12 dni wolnych od pracy - w powyzszej funkcji pominieto pierwszy dzień Zielonych Świątek. (http://www.pit.pl/dni_ustawowo_wolne_od_pracy_287.php)
Aby go uwzględnić, należy do funkcji dodać dwie linijki (np. jako linie 23-24):
$zs = date('m-d', strtotime('+49 days', $date)); 
$hol[11] = $zs;

2009-04-20 11:52 gość_hol

froggy, to prawda nie ma tego święta w tej funkcji jednak jest ono świętem ruchomym i przypada 49 dni (7 tygodni) od Niedzieli Zmartwychwstania Pańskiego, a więc przypada zawsze w niedzielę. Oczywiście jeśli ktoś planowo pracuje w niedziele to miałoby to znaczenie, jednak dla takich potrzeb ta funkcja i tak wymaga modyfikacji.

2010-09-23 19:33 nospor

Na forum pojawił się kod, który wylicza datę od danej po minięciu określonej liczby dni.
http://forum.nospor.pl/programowanie/php/dni-robocze-ft30.html

2011-05-19 15:36 gość_froggy

Ponownie sięgam po tę funkcję
Dla nowoodwiedzających - należy zwrócić uwagę, że od czasu powstania tej funkcji, zmieniły się przepisy - trzeba dodać stałe święto 6.01, a sugestia od szakal_kp, związana z "oddawaniem" dnia wolnego za święto przypadające w dzień wolny od pracy jest już nieaktualna.

2011-05-20 10:33 nospor

$froggy oczywiście masz rację. Już poprawiłem funkcję o dodatkowe święto Trzech Króli. Tylko tego święta nie można traktować jako stałe tak jak inne stałe, gdyż to święto jest stałe dopiero od 2011 roku. Dlatego też w kodzie dodałem warunek na rok podczas brania pod uwagę tego święta.

2011-08-04 11:42 gość_Fifi209

A jakbyś tak podawał wartość bezwzględną? Nie byłoby problemu z ujemnymi.

2011-08-04 11:53 nospor

Fifi ale ja nie mam problemu z ujemnymi. Ja specjalnie tworzę liczbę ujemną, gdy pierwsza data jest większa od drugiej.

Przykład:
gdy ktoś poda zakres dat: od 1maj do 5maj - to mu się wyświetli liczba dodania
gdy ktoś poda zakres dat: od 5maj do 1maj - to mu się wyświetli liczba ujemna
Tak jest zrobione specjalnie

2012-07-30 18:34 gość_adq

liczy źle, jeśli data początkowa jest w weekend albo święto (o 1 za mało)

2012-07-31 08:24 nospor

Możesz podać przykład, dla którego ci źle policzył? Bo mi się takiego nie udało znaleźć.

2015-08-27 10:42 gość_Łukasz Socha

Może komuś się przyda funkcja do sprawdzania czy dana data jest dniem roboczym http://lukasz-socha.pl/php/skrypt-do-sprawdzania-dni-roboczych/

2015-09-20 08:06 gość_marek

A jak zmodyfikować tę funkcję aby wyświetliła również liczbę poniedziałków, wtorków itd. wśród dni roboczych ?

2015-09-20 20:27 nospor

W tym IFie
if (!($weekDay==0 || $weekDay==6 || in_array($md,$hol) || $year>2010 && $md=='01-06')) {
$count++;
}
Dodac sprawdzanie jakim dniem jest dana data. Funkcja date() zwraca takie informacje

Dodaj komentarz

 

Dostępne bbcode: b, u, i, url, quote, code, php, css, html, sql, js

Ostatnio komentowane

  1. Docker - zaprzęgamy ... przez nekih82
  2. Docker - zaprzęgamy ... przez nospor
  3. Docker - zaprzęgamy ... przez szymon
  4. Przenosiny przez nospor
  5. Przenosiny przez RRR
  6. Przenosiny przez nospor
  7. Przenosiny przez MarioEM

Ostatnio na forum

  1. Formularz kontaktowy przez bubaluki
  2. Formularz kontaktowy przez nospor
  3. Formularz kontaktowy przez bubaluki
  4. Formularz kontaktowy przez nospor
  5. Formularz kontaktowy przez bubaluki
  6. Formularz kontaktowy przez nospor
  7. Formularz kontaktowy przez bubaluki

Skrypty użytkowników

  1. Klasa obsługi szablo... przez Lirdoner
  2. Sekcje przez user76
  3. Klasa walidująca for... przez user76
  4. Licznik Gości online przez korey
  5. Form Builder przez Comandeer
  6. Dynamiczny licznik z... przez korey
  7. Captcha przez Comandeer