我当前正在生成一个html表,该表的标题中包含日期
这些日期大概是整个一年中的每周的第一天(显示的年份可能会根据过滤器而变化),它们是由以下代码生成的
<?php $firstDay = strtotime($year . 'W' . str_pad($week, 2, '0', STR_PAD_LEFT)); ?>
<td><?= date('d/m/Y', $firstDay) ?></td>
这是在for
循环内,该循环使$week
从1
到全年的周数。
我注意到,有些年来,上一年的12月的最后一个星期一也被包含在其中,例如当我在过滤器中选择29/12/2014
时的2015
。
到目前为止,为了确定一个月中的星期数,我习惯于通过编程方式计算所述月份中的星期一数,并将其用作日期行上方行的colspan,因此,没有计数几年的1月为数周,这使表格发生了变化。
2015
年呈现的html看起来像这样
<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>
[...]
在每月搜索和测试了很多星期的计数器之后,我发现这些计数器似乎都没有包含上一年的最后一个星期一。
有人能找出如何计算包括上一年发生的那一周在内的周数吗?
答案 0 :(得分:1)
最近有一个与Carbon类似的列表。 这里是一些示例输出的片段:
<?php
use Carbon\Carbon;
$counter = Carbon::createFromDate(2018, 1, 1);
$end = $counter->copy()->endOfYear();
$months = [];
for (; $counter <= $end; $counter->addWeek()) {
// just to avoid E_NOTICE
if (!isset($months[$counter->month])) {
$months[$counter->month] = [
'count' => 0,
'weekstarts' => [],
];
}
++$months[$counter->month]['count'];
$months[$counter->month]['weekstarts'][] = $counter->copy();
}
foreach ($months as $month) {
printf('Month has %d weeks', $month['count']);
echo PHP_EOL;
foreach ($month['weekstarts'] as $num => $weekStartDate) {
printf('Week %d starts at %s', $num + 1, $weekStartDate);
echo PHP_EOL;
}
echo PHP_EOL;
}
答案 1 :(得分:1)
您可以尝试使用此功能:
id
答案 2 :(得分:1)
给定月份的周数基本上是一个月中的天数,加上偏移量,该偏移量取决于该月开始在一周中的哪一天除以7。这是使用{{3 }}和DateInterval:
/**
* 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));
礼物:
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
)
这可以根据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
答案 3 :(得分:0)
所以,这是我的转机,使用了用于生成每周第一天的功能
function getIsoWeeksInYear($year) {
$date = new DateTime;
$date->setISODate($year, 53);
return ($date->format("W") === "53" ? 53 : 52);
}
function getWeeksPerMonth($year) {
$allWeeks = $this->getIsoWeeksInYear($year);
$allFirstDays = [];
for ($i = 0; $i < $allWeeks; $i++) {
$allFirstDays[] = date('m/Y', strtotime($year . "W" . str_pad($i, 2, "0", STR_PAD_LEFT)));
}
$countWeek = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
foreach ($allFirstDays as $firstDay) {
$theMonth = explode('/', $firstDay);
for ($i = 1; $i < 13; $i++) {
if ($theMonth[0] == $i) {
$countWeek[$i - 1]++;
}
}
}
return $countWeek;
}
因此,我们的想法是获取整个星期数数组,并将其循环用于colspans
<?php $span = getWeeksPerMonth($year) ?>
<?php for ($i = 1; $i < 13; $i++): ?>
<th colspan="<?= $span[$i - 1] ?>"><?= strftime('%B', mktime(0, 0, 0, $i)) ?></th>
<?php endfor ?>
对于下面的行,我只使用我之前在问题中已经使用的
<?php for ($i = 0; $i < getIsoWeeksInYear($year); $i++): ?>
<?php $firstDay = strtotime($year . 'W' . str_pad($week, 2, '0', STR_PAD_LEFT)); ?>
<th><?= date('d/m/Y', $firstDay) ?></th>
<?php endfor ?>
因此,可能在1月的某个星期包含上一年,而在12月的某个星期可能包含明年。
也许,某些地方仍有一些东西需要调整。无论如何,我会测试其他答案,我想我会标记最简单的答案。
修改
看起来好像不必爆炸获取的日期,因为我最初以为在上一年开始的那一周必须在某种情况下使用年份