0

I like to iterate through all weeks in a date range that spawns 2 years. Starting at the current week number two years ago, until the current week number this year.

The problem is that a year can either have 52 weeks or 53 weeks, for example:

  • 2015 had 53 weeks (the 53th was from 2015-12-28 till 2016-01-03)

  • 2016 had 52 weeks (the 52th was from 2016-12-26 till 2017-01-01)

So this is currently my php code:

# 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);
Pascal Klein
  • 23,665
  • 24
  • 82
  • 119

3 Answers3

5

Instead of trying to keep track of the bounds, let PHP do it for you.

$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";
}

Demo

John Conde
  • 217,595
  • 99
  • 455
  • 496
  • Your solution has a similar weired bug to Ross solution, it prints: "52 of 2015", "53 of 2016", "01 of 2016", ... – Pascal Klein Jan 04 '17 at 13:44
  • That's because according to the ISO standard there are 53 weeks in that year – John Conde Jan 04 '17 at 13:57
  • 1
    It is important so set the week day to thursday, because according to ISO 8601, the week "belongs" to the year which still contains the thursday. – Pascal Klein Jan 04 '17 at 16:25
  • This answer is almost correct but not quite, since not set the day to thursday. Please look at my answer, it is the only correct one so far. – Pascal Klein Jan 07 '17 at 18:59
3

With the help of Ross Wilson and John Conde I found a solution:

$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");
}

It is important so set the week day to thursday, because according to ISO 8601, the week "belongs" to the year which still contains the thursday.

Pascal Klein
  • 23,665
  • 24
  • 82
  • 119
  • Thanks for the tip on using Thursday as the basis for ISO's week numbering. [Wikipedia has a in-depth explanation](https://en.wikipedia.org/wiki/Week#Week_numbering) if one wants to learn more. – Igor Klimer Jun 13 '21 at 12:45
1

You could use DateTime and setISODate for something like this:

$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");
}

Hope this helps!

Rwd
  • 34,180
  • 6
  • 64
  • 78
  • Your solution seems good, but it has a weired bug, because it prints: "01 2014", "02 2015",... So because the the 53 week of 2014 is the 1 of 2015 it prints "01 2014" – Pascal Klein Jan 04 '17 at 13:41
  • Yes, because the first week of 2015 actually started in 2014. – Rwd Jan 04 '17 at 13:45