Working day script

Asked

Viewed 8,573 times

4

I’m using a script I found in this question Soen, and to count the working days disregarding Saturday and Sunday (can only do with Sunday tbm, changing $what_day > 5 for $what_day > 6 for example) it works right, but I wanted to include the official calendar of holidays in Brazil.

This is the script that is working (already taking the data from my form):

    <?php
//get current month for example
$beginday = ($_POST ["Tdesl"]);
$lastday  = ($_POST ["Tinsem3"]);

$nr_work_days = getWorkingDays($beginday, $lastday);
echo $nr_work_days;

function getWorkingDays($startDate, $endDate)
{
    $begin = strtotime($startDate);
    $end   = strtotime($endDate);
    if ($begin > $end) {
        echo "startdate is in the future! <br />";

        return 0;
    } else {
        $no_days  = 0;
        $weekends = 0;
        while ($begin <= $end) {
            $no_days++; // no of days in the given interval
            $what_day = date("N", $begin);
            if ($what_day > 5) { // 6 and 7 are weekend days
                $weekends++;
            };
            $begin += 86400; // +1 day
        };
        $working_days = $no_days - $weekends;

        return $working_days;
    }
}

THE HTML:

<form method="post" id="Cform" name="Tform" action="diasuteis2.php">
    <label for="Cinsem">Data inicial:</label>
    <input type="date" name="Tinsem3" id="Cinsem" size="6">
    <label for="Cdesl22">Data final:</label>
    <input type="date" name="Tdesl" id="Cdesl22" size="6"><br><br>
    <p align="center">
    <input type="submit" id="enviar"></p>
</form>

An example of correct output for:

echo $beginday;
echo "<br><br>";
echo $lastday;
echo "<br><br>";
echo $nr_work_days;

IS:

2014-12-10

2014-12-15

4

(He considered the 10th, and excluded the 13th and 14th correctly)

Is it possible or feasible to include holidays in this code? If someone can make an example (of course you don’t need to include all holidays, just show how I can do it) I appreciate it now.

  • 2

    Basically you need to have a list, an array of holiday dates. I suggest that you avoid defining Saturday and Sunday as "non-working" days because that is not always the case. Restaurants, for example, sell more on the weekends and usually take off on weekdays when it has low movement. For these, Saturday and Sunday are working days. As for holidays, it also needs to assess regional and municipal holidays such as indefinite holidays. You need to focus more on the logic of holidays so you can play with the calendar. Of course, all this if you want to make the script reusable.

  • 1

    I found an interesting package from a quick search. However, it is necessary to define holidays via array https://github.com/ministryofjustice/date-utils

2 answers

7


I leave here an example for counting the holidays. Note that this has not been tested, so there may be some error.

function getWorkingDays($startDate, $endDate) {
    $begin = strtotime($startDate);
    $end   = strtotime($endDate);
    if ($begin > $end) {
        echo "startdate is in the future! <br />";
        return 0;
    }
    else {
        $holidays = array('01/01', '25/12', ...);
        $weekends = 0;
        $no_days = 0;
        $holidayCount = 0;
        while ($begin <= $end) {
            $no_days++; // no of days in the given interval
            if (in_array(date("d/m", $begin), $holidays)) {
                $holidayCount++;
            }
            $what_day = date("N", $begin);
            if ($what_day > 5) { // 6 and 7 are weekend days
                $weekends++;
            };
            $begin += 86400; // +1 day
        };
        $working_days = $no_days - $weekends - $holidayCount;

        return $working_days;
    }
}
  • 1

    important to inform that $begin and $end must be timestamps, as the values returned by the functions time() and strtotime()

  • 1

    @Sanction I am assuming so. It has been said that the script is being used and works for counting without the holidays, so this line $what_day = date("N", $begin); Tell me Begin is a timestamp :)

  • 1

    had not noticed that the author’s code already calls the function strtotime(), but information on the need for values to be timestamps is important to avoid error in code execution and can be useful for other users

  • 1

    Actually I just showed the part of the function that was relevant, I didn’t copy the full function of the original post. I’ll change to make it clearer.

  • It is giving a small one-day difference to this online business day calculator http://www.dias-uteis.com/ when I put the dates between 01/01/2015 and 31/12/2015, but I think it is because the script is not considering the final day in the calculation, or it may be an error in the on line calculator (then I will manually check the amount of working days). Anyway it worked perfectly, if you want to include the other national holidays in the answer, it looks like this: $holidays = array('01/01', '03/04', '21/04', '01/05', '07/09', '12/10', '02/11', '15/11', '25/12');. Thanks!

  • Ah, another small detail was that I had to invert in the form the day of beginning and end, because the order of the fields was reversed (the difference was always 0 when I put the initial and final date in the respective fields, but it was only reversing that worked perfectly). But that was simple, just for the record if someone comes to use the same script.

Show 1 more comment

2

I would like to add about the holidays:

    function dias_feriados($ano = null)
    {
        if ($ano === null)
        {
            $ano = intval(date('Y'));
        }

        $pascoa     = easter_date($ano); // Limite de 1970 ou após 2037 da easter_date PHP consulta http://www.php.net/manual/en/function.easter-date.php
        $dia_pascoa = date('j', $pascoa);
        $mes_pascoa = date('n', $pascoa);
        $ano_pascoa = date('Y', $pascoa);

        $feriados = array(
            // Tatas Fixas dos feriados Nacionail Basileiras
            mktime(0, 0, 0, 1,  1,   $ano), // Confraternização Universal - Lei nº 662, de 06/04/49
            mktime(0, 0, 0, 4,  21,  $ano), // Tiradentes - Lei nº 662, de 06/04/49
            mktime(0, 0, 0, 5,  1,   $ano), // Dia do Trabalhador - Lei nº 662, de 06/04/49
            mktime(0, 0, 0, 9,  7,   $ano), // Dia da Independência - Lei nº 662, de 06/04/49
            mktime(0, 0, 0, 10,  12, $ano), // N. S. Aparecida - Lei nº 6802, de 30/06/80
            mktime(0, 0, 0, 11,  2,  $ano), // Todos os santos - Lei nº 662, de 06/04/49
            mktime(0, 0, 0, 11, 15,  $ano), // Proclamação da republica - Lei nº 662, de 06/04/49
            mktime(0, 0, 0, 12, 25,  $ano), // Natal - Lei nº 662, de 06/04/49

            // These days have a date depending on easter
            mktime(0, 0, 0, $mes_pascoa, $dia_pascoa - 48,  $ano_pascoa),//2ºferia Carnaval
            mktime(0, 0, 0, $mes_pascoa, $dia_pascoa - 47,  $ano_pascoa),//3ºferia Carnaval 
            mktime(0, 0, 0, $mes_pascoa, $dia_pascoa - 2 ,  $ano_pascoa),//6ºfeira Santa  
            mktime(0, 0, 0, $mes_pascoa, $dia_pascoa     ,  $ano_pascoa),//Pascoa
            mktime(0, 0, 0, $mes_pascoa, $dia_pascoa + 60,  $ano_pascoa),//Corpus Cirist
        );

        sort($feriados);

        return $feriados;
    }

You indicate the year and it generates an ARRAY with the days of the holidays. Otherwise there are still municipal holidays that should be added to the ARRAY. Particularly I put in a database the municipal holidays, because in the team there are people working in various locations.

To show the dates:

            $feriados = dias_feriados();
            $diaf = count($feriados);
            for ($x=0;$x<$diaf;$x++){
                echo '<p>'.date('Y-m-d',$feriados[$x]).'</p>';
            }   

Browser other questions tagged

You are not signed in. Login or sign up in order to post.