Liczba dni roboczych

2007-10-10 16:04:51
 

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:

1
2
3
<?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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?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==|| $weekDay==|| 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:

1
2
3
4
5
6
<?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:23 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:
1
2
3
4
<?php
if ((in_array(date('m-d',$date1),$hol) && $weekDay==6))   
    
$count--;
?>

Mam nadzieję że komuś się przyda

2009-01-06 07:04:27 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:49 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:21 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):
1
2
$zs = date('m-d', strtotime('+49 days', $date)); 
$hol[11] = $zs;

2009-04-20 11:52:15 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:02 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:08 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:55 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:48 gość_Fifi209

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

2011-08-04 11:53:40 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:36 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:54 nospor

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

Dodaj komentarz

 

Dostępne bbcode: b, u, i, color, size, quote, img, url, list, il (tylko w list), code, php, css, html, sql, js