好吧,我想提出比以下更简单的方法(这也是我最初来到这里的原因),但我认为这是对公认答案的改进。它在技术上也有点短,但更重要的是它适应了 0 天的边缘情况。 (在接受的答案中将打印y years m months 省略单词“and”):
<?php
$datetime1 = new DateTime($asset[$a]['PDate']);
$datetime2 = new DateTime;
$interval = array_filter((array) $datetime1->diff($datetime2));
$spec = ['y' => 'years', 'm' => 'months', 'd' => 'days'];
foreach ($spec as $key => $unit) {
if (array_key_exists($key, $interval)) {
$out[] = "{$interval[$key]} $unit";
}
}
if ((count($out)) > 1) {
$last = array_pop($out);
$out[] = "and $last";
}
echo implode(' ', $out);
这是因为DateInterval 对象(由对DateTime::diff() 的调用产生)包含公共属性,这些属性在转换为数组时映射到关联键。 array_filter 默认删除等于零的值。
还有其他改进/考虑;例如,要遵循复数规则,您可以在forloop 中添加条件:
$spec = ['y' => 'year', 'm' => 'month', 'd' => 'day'];
foreach ($spec as $key => $unit) {
if (array_key_exists($key, $interval)) {
$value = $interval[$key];
if ($value > 1) {
$unit .= 's';
}
$out[] = "$value $unit";
}
}
或者也许您想用逗号加入,除了最后一个元素,在这种情况下,最后一段代码将被重写:
$last = array_pop($out);
if ((count($out)) > 0) {
$last = implode(', ', $out) . " and $last";
}
echo $last;
你可以在这里看到它作为一个函数的作用:https://3v4l.org/vYsE7
或者,如果您更喜欢简明的问题特定变体:https://3v4l.org/9FBP5
该函数非常模块化,但默认几乎完全符合 OP 的要求,除了作为选项传入的最后一个 " 和 " 单词。