PHP: цикл по всем неделям в диапазоне дат (последние 2 года)?

Мне нравится перебирать все недели в диапазоне дат, который составляет 2 года. Начиная с текущего номера недели два года назад и до текущего номера недели в этом году.

Проблема в том, что в году может быть 52 или 53 недели, например:

  • В 2015 году было 53 недели (53-я была с 28 декабря 2015 по 03 января 2016).

  • В 2016 году было 52 недели (52-я была с 26.12.2016 по 01.01.2017).

Итак, в настоящее время это мой php-код:

# start with the current week 2 years ago
$year = date("Y") - 2;
$week = (int) date("W");    // (int) removes leading zero for weeks < 10

$endYear = date("Y");
$endWeek = (int) date("W");

# iterate through all weeks until now
do {
    echo $week. " of ". $year;

    $week++;
    if ($week > 52) { // or greater 53 ?????????????
        $year ++;
        $week = 1;
    }
}
while ($year < $endYear || $week < $endWeek);

person Pascal Klein    schedule 04.01.2017    source источник
comment
Я хотел бы знать, почему меня отвергли, чтобы я мог стать лучшим участником этого сообщества.   -  person Pascal Klein    schedule 07.01.2017


Ответы (3)


Вместо того, чтобы пытаться отслеживать границы, позвольте PHP сделать это за вас.

$start    = new DateTime('-2 years');
$end      = new DateTime();
$interval = new DateInterval('P1W');
$period   = new DatePeriod($start, $interval, $end);
foreach ($period as $date) {
    echo $date->format('W') . " of ". $date->format('Y') . "\n";
}

Демо

person John Conde    schedule 04.01.2017
comment
В вашем решении есть ошибка, похожая на Weired, что и в решении Ross, оно печатает: 52 за 2015 год, 53 за 2016 год, 01 за 2016 год, ... - person Pascal Klein; 04.01.2017
comment
Это потому, что согласно стандарту ISO в этом году 53 недели. - person John Conde; 04.01.2017
comment
Поэтому важно установить день недели на четверг, потому что в соответствии с ISO 8601 неделя относится к году, который все еще содержит четверг. - person Pascal Klein; 04.01.2017
comment
Этот ответ почти правильный, но не совсем, поскольку не установлен день на четверг. Посмотрите, пожалуйста, на мой ответ, пока он единственно правильный. - person Pascal Klein; 07.01.2017

С помощью Росса Уилсона и Джона Конде я нашел решение:

$now = new DateTime;

$from = (new DateTime)->setISODate($now->format('Y') - 2, $now->format('W'));
$from->modify("thursday this week"); // see ISO 8601 

while($from < $now) {
    echo $from->format('W Y').'<br />';

    $from->modify("+1 week");
}

Поэтому важно установить день недели на четверг, потому что согласно ISO 8601 неделя «принадлежит» году, в котором еще есть четверг.

person Pascal Klein    schedule 04.01.2017
comment
Спасибо за совет об использовании четверга в качестве основы для нумерации недель ISO. В Википедии есть подробное объяснение, если кто-то хочет узнать больше. - person Igor Klimer; 13.06.2021

Вы можете использовать DateTime и setISODate примерно так:

$now = new DateTime;

$from = (new DateTime)->setISODate($now->format('Y') - 2, $now->format('W'));

while($from < $now) {

    echo $from->format('W Y').'<br />';

    $from->modify("1 week");
}

Надеюсь это поможет!

person Rwd    schedule 04.01.2017
comment
Ваше решение кажется хорошим, но в нем есть устаревшая ошибка, потому что оно печатает: 01 2014, 02 2015, ... Итак, поскольку 53 неделя 2014 года - это 1 неделя 2015 года, оно печатает 01 2014 - person Pascal Klein; 04.01.2017
comment
Да, потому что первая неделя 2015 года фактически началась в 2014 году. - person Rwd; 04.01.2017