我在数据库中有条目,我想按它们发生的那一周分组。我要做的是确定条目发生的一年中的一周,然后显示该周以及该周的周一和周五。这个页面http://princeave.com/bo/test.php显示了我得到的输出。请注意,周一和周五对于2017年发生的事件是正确的,但对于2018年的事件则不正确。代码如下。我错过了什么?
<?php //Gets list of weeks that I can bill
try {
$stmt2 = $db->prepare("SELECT DISTINCT YEAR(transaction_date) AS YR, WEEK(bo_hourly_charges.transaction_date) as wk FROM bo_hourly_charges WHERE billed_by='AfterCare' ORDER BY transaction_date DESC");
$stmt2->execute();
// set the resulting array to associative
$result2 = $stmt2->setFetchMode(PDO::FETCH_ASSOC);
$count = $stmt2->rowCount();
}
catch(PDOException $e) {
echo "Error: " . $e->getMessage();
}
?>
<div align='center'>
<br>
<?php
foreach (($stmt2) as $row) {
$fix = $row['YR']."W".$row['wk'];
$monday=date('M d',strtotime($fix));
$friday=date('M d',strtotime($fix.'5'));
print $fix." ".$row['wk']." ".$monday."-".$friday."<br>";
++$i;
}
?>
有趣的问题,我不知道PHP允许这种格式。我不相信它是记录在案的行为。因此,依赖它可能并不明智。
Running your code with the full range of weeks in 2017很快表明问题与2018年无关:
<?php
$dates = [];
for ($i = 1; $i <= 52; $i++) {
$dates[] = ['YR' => 2017, 'wk' => $i];
}
foreach ($dates as $row) {
$fix = $row['YR']."W".$row['wk'];
$monday=date('M d',strtotime($fix));
$friday=date('M d',strtotime($fix.'5'));
print $fix." ".$row['wk']." ".$monday."-".$friday."\n";
++$i;
}
产量:
(...)
2017W5 5 Dec 31-Dec 31
2017W6 6 Dec 31-Dec 31
2017W7 7 Dec 31-Dec 31
2017W8 8 Dec 31-Dec 31
2017W9 9 Dec 31-Dec 31
2017W10 10 Mar 06-Mar 10
2017W11 11 Mar 13-Mar 17
2017W12 12 Mar 20-Mar 24
2017W13 13 Mar 27-Mar 31
2017W14 14 Apr 03-Apr 07
(...)
相反,它似乎在2017年的前九周有类似的问题。从第10周开始,问题似乎已得到解决。
第1周到第9周以及第10周和第10周之间的差异与格式密切相关。
Padding the weeks with a zero似乎解决了这个问题:
<?php
$dates = [];
for ($i = 1; $i <= 52; $i++) {
$dates[] = ['YR' => 2017, 'wk' => $i];
}
foreach ($dates as $row) {
$fix = $row['YR']."W".str_pad($row['wk'], 2, '0', STR_PAD_LEFT);
$monday=date('M d',strtotime($fix));
$friday=date('M d',strtotime($fix.'5'));
print $fix." ".$row['wk']." ".$monday."-".$friday."\n";
++$i;
}
然而,更明智的选择是使用更常见的日期格式。
根据official documentation,ISO year with ISO week and day
的正确复合日期定义如下:
YY "-"? "W" W "-"? [0-7]
其中破折号(-
)是可选的(这是在它们之后附加的问号?
的含义)。因此,你的格式没有任何问题...但你的代码会发生什么,例如,2018W4
(2018年第4周)变成2018-W45
(2018年第45周),一切都搞砸了。为了避免模糊格式,请确保您的周数始终包含two digits
(从01
到53
)通过零填充:
$fix = $row['YR'].'W'.sprintf('%02d',$row['wk']);
另外,如果要使用准备好的SQL语句,则应避免在查询中手动插入参数。否则你将无法实现这种方法的主要目的之一:安全。
$stmt2 = $db->prepare("SELECT DISTINCT YEAR(transaction_date) AS YR, WEEK(bo_hourly_charges.transaction_date) as wk FROM bo_hourly_charges WHERE billed_by=? ORDER BY transaction_date DESC");
$stmt2->bind_param('s','AfterCare');