How to know how many Sundays have the months of the year php mysql

8

Let's say the year is: 2016  I need to know how many Sundays have the months of the year and record and result in variable php.  Reason:  I need to pass a condition, for example:

if ($dom_mes == 4 )
{     
    //CONDIÇÃO A     
} 
elseif ($dom_mes == 5 )
{
    //CONDIÇÃO B    
}
else
{
    //NADA A FAZER    
}
    
asked by anonymous 21.10.2016 / 15:48

3 answers

7

May take month by month. I modified the example to loop:

<?php
$array = [];
$ano = 2016;


for($i = 1; $i <= 12; $i++){
    $data = $ano . '-' . $i. '-01';

    $inicio = new DateTime($data);
    $fim = new DateTime($inicio->format('Y-m-t'));
    $dias = $inicio->diff($fim, true)->days;

    $array[$i] = intval($dias / 7) + ($inicio->format('N') + $dias % 7 >= 7);
}
?>
<pre>
<?=print_r($array) ?>
</pre>
    
21.10.2016 / 16:27
6

Here's a workaround:

function domingosNoMes( $mes, $ano ) {
    $t = gmmktime( 0, 0, 0, $mes, 1, $ano );
    $ult = date( 't', $t );
    $sem  = date( 'w', $t );
    return floor( ( $ult - 1 ) / 7 ) + ( $sem == 0 || $sem > ( 35 - $ult ) );
}

See working at IDEONE .

It is similar to the mathematical technique of Hugo Leonardo, which dispenses use of loops , only changes the part of using native functions directly, without objects.

If you want, you can simplify further by using N instead of w in date , if you do not need compatibility with older versions of PHP, making it easy to remove || of expression with a small setting.

Remember that if you are using a 32-bit PHP, using timestamps only works until 2038. Now, if someone is still using things in 32 bits in full 2038, serious that timestamp : D

    
21.10.2016 / 17:24
2

One more

<?php

$week_day = 1; // The desired week day (sunday: 1, monday:2 .... saturday: 0)
$year = '2016'; // Year, 4 digits

$rs = array();
$month = 1;
while ($month <= 12) {
    $day = 1;
    $date = new DateTime($year.'-'.$month.'-'.$day);
    $day_last = $date->format('t');
    $i = 1;
    while ($day <= $day_last) {
        $date->add(new DateInterval('P'.$i.'D'));
        //$date->add(date_interval_create_from_date_string($i.' days'));
        $day_week = $date->format('w');
        if ($day_week == $week_day) {
            $rs[$month][] = $day;
            $i = 7;
        }
        $day += $i;
    }
    $month++;
}

echo '<pre>';
print_r($rs);
echo '</pre>';

Maintains a single instance of DateTime() for each month instead of creating an instance for each day of each month.

Do not go every day of every month.
When identifying the first "Sunday", the counter jumps from 7 to 7, bringing a considerable gain of perfomance than checking day by day. That is, instead of doing 365/366 iterations, it only makes something around 52.

The routine is reusable. Just change the code of the day of the week and the year to get results for other days or years.

1: Domingo
2: Segunda
3: Terça
4: Quarta
5: Quinta
6: Sexta
0: Sábado

Return is a multidimensional array. For the year 2016, this is the result:

Array
(
    [1] => Array
        (
            [0] => 3
            [1] => 10
            [2] => 17
            [3] => 24
            [4] => 31
        )

    [2] => Array
        (
            [0] => 7
            [1] => 14
            [2] => 21
            [3] => 28
        )

    [3] => Array
        (
            [0] => 6
            [1] => 13
            [2] => 20
            [3] => 27
        )

    [4] => Array
        (
            [0] => 3
            [1] => 10
            [2] => 17
            [3] => 24
        )

    [5] => Array
        (
            [0] => 1
            [1] => 8
            [2] => 15
            [3] => 22
            [4] => 29
        )

    [6] => Array
        (
            [0] => 5
            [1] => 12
            [2] => 19
            [3] => 26
        )

    [7] => Array
        (
            [0] => 3
            [1] => 10
            [2] => 17
            [3] => 24
            [4] => 31
        )

    [8] => Array
        (
            [0] => 7
            [1] => 14
            [2] => 21
            [3] => 28
        )

    [9] => Array
        (
            [0] => 4
            [1] => 11
            [2] => 18
            [3] => 25
        )

    [10] => Array
        (
            [0] => 2
            [1] => 9
            [2] => 16
            [3] => 23
            [4] => 30
        )

    [11] => Array
        (
            [0] => 6
            [1] => 13
            [2] => 20
            [3] => 27
        )

    [12] => Array
        (
            [0] => 4
            [1] => 11
            [2] => 18
            [3] => 25
        )

)

Just iterate through the result to extract what you need.
I preferred to skip this part because iterating array() is very basic.

Another relevant point is that the routine will still work even after the year 2038.
Of course in 2038 will be rare or null anyone using 32 bit systems. The concern is with the current age. Many still use 32-bit systems today and may want to do operations with dates after 2038 under environments in those environments, which may return erroneous results.

One more detail, regardless of the solution you choose, save the result to a static file or even to a database because if you need to run again you do not have to run it all over again. If executed once, the second time onwards is redundant since it will always yield the same result. This is a question of performance and optimization. Do your best.

Optimized version

This new optimized version runs 0.21 milliseconds. The previous runs in 0.245 milliseconds. It also consumes less memory, saving about 458 bytes from the original

It follows the same logic as the original with the difference that only one instance of Datetime() is now created.

What kills performance a little is having to invoke $date->format('m') and $date->format('d') to get the month and day. Which are optional because the question does not ask for this. But I preferred to show a more detailed result telling you which days were found on the day of the week, in the case on Sunday.

The repetition limit is the total number of days in the year. The total is 366 for leap year and 365 for non-leap year.

When finding the first "Sunday", the increments are every 7 days, thus preventing the loop from looping 365 or 366 times. In this scheme, we have only 54 iterations.

$week_day = 0; // The desired week day (sunday: 1, monday:2 .... saturday: 0)
$year = '2016'; // Year, 4 digits

$rs = array();
$days = (((($year % 4) == 0) && ((($year % 100) != 0) || (($year %400) == 0))))? 366: 365;
$date = new DateTime(($year - 1).'-12-31');
$day = 1;
$i = 1;
while ($day <= $days) {
    $date->add(new DateInterval('P'.$i.'D'));
    //$date->add(date_interval_create_from_date_string($i.' days'));
    $day_week = (int)$date->format('w');
    if ($day_week == $week_day) {
        $rs[(int)$date->format('m')][] = (int)$date->format('d');
        $i = 7;
    }
    $day += $i;
}

echo '<pre>';
print_r($rs);
echo '</pre>';

I also made a change in both versions in the following snippet

    $date->add(new DateInterval('P'.$i.'D'));
    //$date->add(date_interval_create_from_date_string($i.' days'));

The original version was built with PHP running under Android. In this PHP does not have class DateInterval() even being version 7. So I used date_interval_create_from_date_string() .

Now I did using a Windows Pc and I was able to optimize more by switching back to new DateInterval() because date_interval_create_from_date_string() is an alias of it. Alias (shortcut) functions are always slower.

    
21.10.2016 / 17:53