如何在 PHP 中获取每月的周数?

pro*_*out 2 php algorithm date

我目前正在生成一个 html 表,其中包含标题中的日期

这些日期据称是全年每周的第一天(显示的年份可能会根据过滤器发生变化),它们是由以下代码生成的

<?php $firstDay = strtotime($year . 'W' . str_pad($week, 2, '0', STR_PAD_LEFT)); ?>
<td><?= date('d/m/Y', $firstDay) ?></td>
Run Code Online (Sandbox Code Playgroud)

这是一个for循环,它使$week从 变为1全年的周数。

我注意到,有些年来,前一年 12 月的最后一个星期一也包含在其中,例如29/12/2014当我2015在过滤器中选择时。

到目前为止,为了确定一个月中的周数,我曾经以编程方式计算该月中星期一的数量,并将其用作日期行上方行的 colspan,因此,一月有无数周多年来,这使得桌子发生了变化。

今年渲染的 html2015看起来像这样

<table>
    <thead>
        <tr>
            <th colspan="4">January</th>
            <th colspan="4">February</th>
            [...]
        </tr>
        <tr>
            <!-- Under January cell -->
            <th>29/12/2014</th>
            <th>05/01/2015</th>
            <th>12/01/2015</th>
            <th>19/01/2015</th>
            <!-- Under February cell -->
            <th>26/01/2015</th>
            <th>02/02/2015</th>
            [...]
        </tr>
    </thead>
    [...]
Run Code Online (Sandbox Code Playgroud)

在搜索和测试了很多周每月计数器之后,我发现的这些计数器似乎都不包括上一年的上周一。

谁能找出如何计算周数,包括上一年发生的额外一周?

spi*_*kus 5

给定月份中的周数基本上是一个月中的天数,加上取决于该月开始于一周中的哪一天的偏移量,除以 7。以下是使用 DateInterval 和 DatePeriod解决方案

/**
 * Get number of weeks starting *Monday*, occuring in a given month.
 * A week occurs in a month if any day from that week falls in the month.
 * @param $month_date is expected to be DateTime.
 * @param $count_last count partial week at the end of month as part of month.
 */
function weeks_in_month($month_date, $count_last=true) {
  $fn = $count_last ? 'ceil' : 'floor';
  $start = new DateTime($month_date->format('Y-m'));
  $days = (clone $start)->add(new DateInterval('P1M'))->diff($start)->days;
  $offset = $month_date->format('N') - 1;
  return $fn(($days + $offset)/7);
}

/**
 * Wrapper over weeks_in_month() to get weeks in month for each month of a given year.
 * @param $year_date is expected to be a DateTime.
 */
function year_month_weeks($year_date, $count_last=true) {
  $start = new DateTime($year_date->format('Y') . '-01');
  $year_month_weeks = [];
  foreach(new DatePeriod($start, new DateInterval('P1M'), 11) as $month) {
    $year_month_weeks[] += weeks_in_month($month, $count_last);
  }
  return $year_month_weeks;
}

print_r(year_month_weeks(new DateTime('2008-01'), true));
Run Code Online (Sandbox Code Playgroud)

给出:

Array
(
    [0] => 5
    [1] => 5
    [2] => 6
    [3] => 5
    [4] => 5
    [5] => 6
    [6] => 5
    [7] => 5
    [8] => 5
    [9] => 5
    [10] => 5
    [11] => 5
)
Run Code Online (Sandbox Code Playgroud)

这可以根据 的输出进行验证cal。2008 年前 6 个月,3 月、6 月应有 6 周,其余 5 周:

>ncal -Mb -m 1 -A 5 2008
                            2008
      January               February               March          
Mo Tu We Th Fr Sa Su  Mo Tu We Th Fr Sa Su  Mo Tu We Th Fr Sa Su  
    1  2  3  4  5  6               1  2  3                  1  2  
 7  8  9 10 11 12 13   4  5  6  7  8  9 10   3  4  5  6  7  8  9  
14 15 16 17 18 19 20  11 12 13 14 15 16 17  10 11 12 13 14 15 16  
21 22 23 24 25 26 27  18 19 20 21 22 23 24  17 18 19 20 21 22 23  
28 29 30 31           25 26 27 28 29        24 25 26 27 28 29 30  
                                            31                    

       April                  May                   June          
Mo Tu We Th Fr Sa Su  Mo Tu We Th Fr Sa Su  Mo Tu We Th Fr Sa Su  
    1  2  3  4  5  6            1  2  3  4                     1  
 7  8  9 10 11 12 13   5  6  7  8  9 10 11   2  3  4  5  6  7  8  
14 15 16 17 18 19 20  12 13 14 15 16 17 18   9 10 11 12 13 14 15  
21 22 23 24 25 26 27  19 20 21 22 23 24 25  16 17 18 19 20 21 22  
28 29 30              26 27 28 29 30 31     23 24 25 26 27 28 29  
                                            30       
Run Code Online (Sandbox Code Playgroud)