Разбиение месяца по неделям в PHP

110
05 января 2022, 06:20

Нужно вывести статистику по неделям. Для этого желателен массив с неделями по дням. Например возьмем текущий месяц (Декабрь)

1ая неделя - 01.12.2019 (Вс)
2ая неделя - с 02.12.2019 (Пн) по 08.12.2019 (Вс)
3ая неделя - с 9.12.2019 (Пн) по 15.12.2019 (Вс)
4ая неделя - с 16.12.2019 (Пн) по 22.12.2019 (Вс)
5ая неделя - с 23.12.2019 (Пн) по 29.12.2019 (Вс)
6ая неделя - с 30.12.2019 (Пн) по 31.12.2019 (Вт)

И сам массив:

[0] = [1];
[1] = [2, 3, 4, 5, 6, 7, 8];
[2] = [9, 10, 11, 12, 13, 14, 15];
[3] = [16, 17, 18, 19, 20, 21, 22];
[4] = [23, 24, 25, 26, 27, 28, 29];
[5] = [30, 31];

С переходом на след месяц

1ая неделя - с 1.01.2019 (Ср) по 5.01.2019 (Вс) и тд.

Answer 1

Можно написать примерно следующую функцию, которая будет генерировать необходимый двумерный массив, элементами которого являются недели месяца.

function getWeeksOfMonth(string $data): array
{
    $arrayOfWeeks = [];
    $period = new DatePeriod(
        DateTime::createFromFormat('!Y-n-d', $data),
        new DateInterval('P1D'),
        DateTime::createFromFormat('!Y-n-d', $data)->add(new DateInterval('P1M'))
    );
    foreach ($period as $weeks) {
        $arrayOfWeeks[$weeks->format('W')][] = $weeks;
    }
    $arrOfDays = function($stack): array {
        foreach ($stack as $w => $date) {
            $base[] = range($date[0]->format('d'), $date[count($date)-1]->format('d'));
        }
        return $base;
    };
    return $arrOfDays($arrayOfWeeks);
}

Проверяем функцию и смотрит конечный результат:

foreach (getWeeksOfMonth('2019-12-01') as $k => $v) echo join(', ', $v) . PHP_EOL;
// 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

https://3v4l.org/cgnc5

Думаю дальше не будет проблемой самостоятельно привести результат в нужный вид.

Answer 2

Тут основная проблема с локализацией даты. В зависимости от локали будут печататься дни не дели на языке локали.

Вот пример

$dateStart="01 december 2019";
$dt= strtotime( $dateStart);
$currdt=$dt;
$nextmonth=strtotime($dateStart."+1 month"."-1 day");
$i=0;
do 
{
    $weekday= (6+date("w",$currdt))%7;
    $endday=abs($weekday-6);
    $startarr[$i]=$currdt;
    $endarr[$i]=strtotime(date("d-m-Y",$currdt)."+$endday day");
    if ($endarr[$i]>=$nextmonth){
        $endarr[$i]=$nextmonth;
    }
    $currdt=strtotime(date("d-m-Y",$endarr[$i])."+1 day");
    $nameOfStartDay = date('D', $startarr[$i]);
    $nameOfEndDay = date('D', $endarr[$i]);
    print(($i+1)."-ая неделя - c ". date("d.m.Y",$startarr[$i])."(".$nameOfStartDay.") по ". date("d.m.Y",$endarr[$i])."(".$nameOfEndDay.")\n");
     $i++;
}while($endarr[$i-1]<$nextmonth);

Вывод

1-ая неделя - c 01.12.2019(Sun) по 01.12.2019(Sun)
2-ая неделя - c 02.12.2019(Mon) по 08.12.2019(Sun)
3-ая неделя - c 09.12.2019(Mon) по 15.12.2019(Sun)
4-ая неделя - c 16.12.2019(Mon) по 22.12.2019(Sun)
5-ая неделя - c 23.12.2019(Mon) по 29.12.2019(Sun)
6-ая неделя - c 30.12.2019(Mon) по 31.12.2019(Tue)
Answer 3

В финансовой системе, конец недели - это утро следующего понедельника, вот решение:

function monthToWeeks($month, $year)
{
    $lastDay = date('d.m.Y', mktime(0, 0, 0, $month+1, 1, $year));
    $weeks = [date('d.m.Y', mktime(0,0,0, $month, 1, $year))];
    for ($i = 2; $i < date('t'); $i++) {
        $t = mktime(0, 0, 0, $month, $i, $year);
        if (date('N', $t) == 1) {
            array_push($weeks, date('d.m.Y', $t));
        }
    }
    array_push($weeks, $lastDay);
    $countOfWeeks = count($weeks) - 1;
    $i = 0;
    echo 'In ' . date('F Y', mktime(0,0,0, $month, 1, $year)) . ' we have ' . 
$countOfWeeks . ' weeks:<br><br>';
    while ($i < $countOfWeeks) {
        echo $i+1 . ' week - from ' . $weeks[$i] . ' to ' . $weeks[$i+1] . '<br>';
        $i++;
    }
}
monthToWeeks(12, 2019);
Output:
In December 2019 we have 6 weeks:
1 week - from 01.12.2019 to 02.12.2019
2 week - from 02.12.2019 to 09.12.2019
3 week - from 09.12.2019 to 16.12.2019
4 week - from 16.12.2019 to 23.12.2019
5 week - from 23.12.2019 to 30.12.2019
6 week - from 30.12.2019 to 01.01.2020
READ ALSO
Как получить имя домена из GET запроса на мой сайт

Как получить имя домена из GET запроса на мой сайт

Суть вопроса такова, имеется база данных, в ней таблица с полями: домен, токенКогда с другого сайта выполняется GET запрос к моему скрипту, мне...

69
CRON не отправляет email. Почему?

CRON не отправляет email. Почему?

CRON не отправляет письма по завершению выполнения задачи, но отправляет, если в скрипте была какая-то ошибка

91
Mysql использование update в запросе

Mysql использование update в запросе

Всем приветПытаюсь обновить оптовую цену товаров, которые были проданы больше 20 раз, но в результате сталкиваюсь с ошибкой

289
Средства работы с БД для Python 3.7

Средства работы с БД для Python 3.7

Переезжаем на микросервисы, в проекте большое количество различных технологий, база однаЛьвиная доля всего этого работает в стеке Java + Jdbi, поэтому...

228