PHP 日期是很棒的东西
+1 year
例如。然而我让自己陷入了一些混乱。我有三个跨越两个月的日期,我想制作一个优雅的字符串
“2 月 28 日、2 月 29 日和 3 月 1 日”,来自 3 个日期的数组,格式为 YYYYMMDD
。确切的日期数量未知,最少 1 可能最多 4
除了一些相当曲折的
str_replace
操作之外,我如何将其输出转换为我想要的格式?
注意:不超过2个月,也许一个月内全部完成。
$dates_array = ['20240228', '20240229', '20240301'];
foreach ($dates_array as $date) :
$datetimes[] = new DateTime($date);
endforeach;
// print_r($datetimes);
foreach ($datetimes as $key=>$date) :
$month = $date->format('F');
$day = $date->format('j');
$date_array[]= $day." ".$month." & ";
endforeach;
$date_string = join( ' ', $date_array ) ;
echo $date_string;
// 28 February & 29 February & 1 March &
我成功地创建了这个:
$dates = ['20240228', '20240229', '20240301'];
function formatDates(array $datesInput) {
foreach ($datesInput as $datesKey => $date) {
$date = new DateTime($date);
$month = $date->format('F');
$day = $date->format('j');
if ($datesKey == 0) {
$datesOutput = $day;
} elseif ($currentMonth <> $month) {
$datesOutput .= " $currentMonth & $day";
} else {
$datesOutput .= ", $day";
}
$currentMonth = $month;
}
return "$datesOutput $month";
}
echo formatDates($dates);
返回:
28, 29 February & 1 March
事情并没有那么复杂。然而,我确实将所有内容都放在一个函数中,因为否则我将不得不创建相当多的全局变量,而这被认为是不好的做法。 有关演示,请参阅:
https://3v4l.org/gUWihimplode
将它们连接在一起:
$dates_array = ['20240228', '20240229', '20240301'];
foreach ($dates_array as $date) {
$date = new DateTime($date);
$datesByMonth[$date->format('F')][] = $date->format('j');
}
foreach($datesByMonth as $month => $dates) {
$datesByMonth[$month] = implode(', ', $dates) . ' ' . $month;
}
echo implode(' & ', $datesByMonth);
https://3v4l.org/6snHe在不同的年份,显然是行不通的,但我想这不是一个要求(?)。
迭代日期,在每次迭代中检查前一个日期是否连续并且属于同一个月。
<?php
$dates_array = ["20240214", "20240228", "20240229", "20240301"];
$datetime_array = array_map(function($date_string) {
return DateTime::createFromFormat("Ymd", $date_string);
}, $dates_array);
$groups = array_reduce($datetime_array, function($groups, $curr) {
$key1 = array_key_last($groups);
if ($key1 === null) {
$key1 = 0;
} else {
$key2 = array_key_last($groups[$key1]);
$prev = $groups[$key1][$key2];
if ($prev->diff($curr)->d !== 1 || $prev->format("n") !== $curr->format("n")) {
$key1 += 1;
}
}
$groups[$key1][] = $curr;
return $groups;
}, []);
$result = array_map(function($group) {
$key1 = array_key_last($group);
return $key1 === 0 ? $group[$key1]->format("j F") : ($group[0]->format("j") . "-" . $group[$key1]->format("j F"));
}, $groups);
echo implode(", ", $result);
// 14 February, 28-29 February, 1 March
$datetimes
时,您必须检查列表中的下一个值是否在同一个月,以便知道是否在该日期的格式化输出中包含月份名称。
这是做到这一点的一种方法。广泛的假设是日期将始终按升序提供,但它也会检查下一个日期是否在同一年以及同一月,以防日期之间存在较大差距。$dates_array = ['20241203', '20240115', '20240116', '20240228', '20240229', '20240301'];
foreach ($dates_array as $date)
{
$datetimes[] = new DateTime($date);
}
foreach ($datetimes as $key=>$date)
{
$dateStr = $date->format('j');
//check if there's another entry after this one
if (isset($datetimes[$key+1]))
{
//check the if following entry is in the same month and year as this one
if ($datetimes[$key+1]->format("ym") == $date->format("ym")) {
$dateStr .= ",";
}
else
{
$dateStr .= " ".$date->format("F")." & ";
}
}
else {
$dateStr .= " ".$date->format("F");
}
$date_array[]= $dateStr;
}
$date_string = join( ' ', $date_array ) ;
echo $date_string;
现场演示:https://3v4l.org/tWrhe
<?php
$dates = ['20240228', '20240229','20240301'];
$countDates = count($dates) - 1;
$output = [];
foreach ($dates as $date) :
$datetimes[] = new DateTime($date);
endforeach;
foreach ($datetimes as $i => $datetime) :
$dateOutput = [$datetime->format('j')];
$isNextMonthTheSame = isset($datetimes[$i+1]) && $datetime->format('m') === $datetimes[$i+1]->format('m');
if (!$isNextMonthTheSame) {
$dateOutput []= ' '. $datetime->format('F');
$dateOutput []= ' & ';
} else {
$dateOutput []= ', ';
}
if ($i === $countDates) {
array_pop($dateOutput);
}
$output []= $dateOutput;
endforeach;
echo implode(array_merge(...$output));
PS:扩展运算符(
...
)已在 PHP 7.4 中实现:
我可能会使用
array_map()
进行第二个循环任务,以便数据可以方便地
implode()
编辑两次。代码:(演示)
$dates = ['20240228', '20240229', '20240301'];
$groups = [];
foreach ($dates as $date) {
$date = new DateTime($date);
$groups[$date->format('F')][] = $date->format('j');
}
echo implode(
' & ',
array_map(
fn($j, $F) => implode(', ', $j) . " $F",
$groups,
array_keys($groups)
)
);
代码:(
演示)
$dates = ['20240228', '20240229', '20240301'];
$text = '';
foreach ($dates as $i => $date) {
$date = new DateTime($date);
$month = $date->format('F');
$day = $date->format('j');
$pos = strpos($text, $month);
if ($pos !== false) {
$text = substr_replace($text, ", $day", $pos - 1, 0);
} else {
$text .= ($text ? ' & ' : '') . "$day $month";
}
}
echo $text;