PHP查找最接近时间线段的日期

7

好的,这可能会涉及到一些数学,希望你带来了你的科学计算器;)

这是我的问题:

alt text

给定一个初始日期(时间戳),时间段期间(秒)和今天的日期(时间戳),我需要找到与周期*n加上原始/初始日期相符的最近日期。

到目前为止,我已经做了一些很好的工作,比如初始和最终(今天)日期之间的“周期”数量,在上面的演示中为“2”:

$initial=strtotime('2 April 1991');
$time=time();
$period=strtotime('+10 years',0);

$periods=round(($time-$initial)/$period);

我接下来做的事情是:
$range=$periods*$period;

最后:
echo date('d M Y',$initial+$range);

这段文字写道“2011年4月3日”。为什么是3号呢?(我猜测这可能与闰年有关?)

你是否有过一种错觉,感觉自己缺少了一些小细节?我现在就有这种感觉...


不像你,我正在测试你的代码,而且我得到的是“2011年4月1日”! - ncuesta
什么?也许你应该注意你的错误指控。事实上,1991年4月1日也是错误的... - Christian
这些时间段是固定的吗?它们总是以年为单位,还是会根据情况变化?如果你只需要处理年份,那么你只需关注年份部分,就能顺利完成任务。但如果你需要处理天数,就会遇到闰年的问题。 - Knubo
错误指责?我只是运行了你的代码并与你分享了结果。 - ncuesta
@ncuesta 这里可能还有其他变量在起作用。没有必要指责别人。 - Russell Dias
显示剩余3条评论
4个回答

2
好的,如果我理解你的问题正确的话,你想知道在一段给定的时间内下一个日期是什么(例如,在1991年4月2日开始的每10年中,下一个日期将是2011年4月2日)。因此,您应该深入了解PHP中更准确的日期处理类DateTime。结合使用DateInterval可以完全满足您的需求。请注意保留HTML标签。
<?php
$interval = new DateInterval('P10Y'); // 10 years
$initial = new DateTime('1991-04-02');
$now = new DateTime('now');

while ($now->getTimestamp() > $initial->getTimestamp()) {
    $initial = $initial->add($interval);
}

echo $initial->format('d M Y'); // should return April 2, 2011 !
?>

同另一个人的问题一样,涉及到数学实现和循环的问题。 - Christian
1
对我来说非常好用。只有一件事:在最后一行,应该是 echo $initial->format('d M Y'); - ncuesta
@Christian Sciberras:你可以尝试在日期对象上进行数学计算:round(($now-$initial)/$interval) * $interval。我现在无法测试,所以不能确认它是否有效。或者,你需要在每个变量中添加 ->getTimestamp() 以进行数学运算(测试)。如果有效,请告诉我,我会编辑我的答案。 - Cyril N.
2
请注意,这将找到离现在最近的日期 之前 的日期,而不是最接近之前或之后的日期。这就像在原问题中运行 floor 而不是 round - lonesomeday
是的,@lonesomeday,你说得对,我误解了nearest和“closest after”。 - Cyril N.

1

试一下这个:

$current = $initial = strtotime('2 April 1991');
$time_span = '+10 years';

while ($current < time())
{ 
  $current = strtotime($time_span, $current);
}

echo date('d M Y', $current);

我得到了1991年4月2日。我采用了一种更数学化的方法,而不是通过循环(在更高范围上循环往往会变得昂贵)。我还需要让它能够进行每月和每周的检查,这使得它变得相当缓慢。 - Christian

1
发生了什么事:
从“公元0年”(1970年)开始的+10年将包括3个闰年'72,'76和'80,但是从'91到'11只有5个闰年'92,'96,'00,'04和'08。您将该时期添加了两次,因此由于没有6个闰年,所以多了一天。
您需要做的是:
使用strtotime逐步添加这个时间段。
$period = "+10 years";
$newTime = $startingTime;
while(<condition>){
    $newTime = strtotime($period, $newTime);
}

啊!我明白了。应该是:strtotime('+1 years',0)* 10。 - Christian
@Christian Sciberras 不要这样做 :) 用strtotime和while循环。我发布了一些模拟代码。如果你使用strtotime('+1 years',0)*3,你会比你需要的少5天。(可能是3月28日。) - Alin Purcaru
那个 while 正是我写的,但是 Christian 在寻找这个问题的数学方法。 - ncuesta

0
作为对cx42net的回答的修复:
<?php

$initial = new DateTime('2 April 1991');
$now = new DateTime('now');
$interval = new DateInterval('P10Y');

$curDate = $initial;

while (true) {
    $curDate = $curDate->add($interval);

    $curDiff = $curDate->diff($now)->days;

    if (isset($lastDiff) && ($curDiff > $lastDiff)) {
        echo $lastDate->format('d M Y');
        break;
    } else {
        $lastDate = clone $curDate;
        $lastDiff = $curDiff;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接