【问题标题】:PHP - Is there a simple way to loop between two dates and fill in missing values?PHP - 有没有一种简单的方法可以在两个日期之间循环并填写缺失值?
【发布时间】:2012-01-06 09:19:56
【问题描述】:

我有两个约会。假设它们看起来像这样。

$start = 2010/12/24;
$end = 2012/01/05;

我查询数据库以查找这两个日期之间的访问。我找到一些。然后我填充了一个名为 stats 的数组。

$stats['2010/12/25'] = 50;
$stats['2010/12/31'] = 25;
...

如您所见,有几天不见了。 我需要用零值填充缺失的日期。我在想这样的事情。 (我已经从开始日期和结束日期中提取了日/月/年。

for($y=$start_year; $y <= $end_year; $y++) {
    for($m=$start_month; $m <=$end_month; $m++) {
        for($d=$start_day; $d <= $end_day; $d++) {

这在一年中可以正常工作,但是月份和日期不起作用。如果开始日是 15 日。随后每个月的第 1-14 天将被错过。那么我可以有这样的解决方案......

for($y=$start_year; $y <= $end_year; $y++) {
    for($m=1; $m <13; $m++) {
         $total_days = cal_days_in_month(CAL_GREGORIAN, $m, $y) + 1;
         for($d=1; $d <= $total_days; $d++) {

然后我需要一堆 if 语句来确保开始和结束的月份和日期是有效的。

有没有更好的方法来做到这一点?或者这甚至可以在我的 mysql 查询中完成吗?

【问题讨论】:

标签: php


【解决方案1】:
$i = 1;
while(date("Y/m/d", strtotime(date("Y/m/d", strtotime($start)) . "+ $i days")) < $end) {
    ... code here ...
    $i++;
}

【讨论】:

    【解决方案2】:

    只是为了展示一些 PHP 较新的间隔处理方法的强大功能(pgl 在他的回答中提到):

    $startDate = DateTime::createFromFormat("Y/m/d","2010/12/24",new DateTimeZone("Europe/London"));
    $endDate = DateTime::createFromFormat("Y/m/d","2012/01/05",new DateTimeZone("Europe/London"));
    
    $periodInterval = new DateInterval( "P1D" ); // 1-day, though can be more sophisticated rule
    $period = new DatePeriod( $startDate, $periodInterval, $endDate );
    
    foreach($period as $date){
       echo $date->format("Y-m-d") , PHP_EOL;
    }
    

    是否需要 PHP >= 5.3.0

    编辑

    如果需要包含实际的结束日期,则需要在 foreach() 循环之前的 $endDate 中添加一天:

    $endDate->add( $periodInterval );
    

    编辑#2

    $startDate = new DateTime("2010/12/24",new DateTimeZone("Europe/London"));
    $endDate = new DateTime("2012/01/05",new DateTimeZone("Europe/London"));
    
    do {
       echo $startDate->format("Y-m-d") , PHP_EOL;
       $startDate->modify("+1 day");
    } while ($startDate <= $endDate);
    

    对于 PHP 5.2.0(或更早版本,如果启用了 dateTime 对象)

    【讨论】:

    • 只是好奇。为什么在 echo 语句中使用参数语法而不是字符串连接?我总是使用.,因此我可以轻松更改要分配给变量的代码行,而不是被echo淘汰。
    • @Treffynnon - 我猜只是习惯的力量......有些人说它比串联更快,但我从未测试过这个理论......但我通常很少在工作代码中使用 echo仅用于测试简单的例程。
    • 谢谢,不幸的是我使用的服务器是 PHP 5.2 :(
    • @JasonS - 我假设 PHP 启用了 dateTime 对象,因此使用 dateTime 对象和 modify() 方法 - uk.php.net/manual/en/datetime.modify.php - 应该可以正常工作,并防止出现任何夏令时问题
    【解决方案3】:

    如果您使用的是 PHP5.3,那么可以使用 Mark Ba​​ker 的答案。如果(正如您在评论中所说)您仍在使用 PHP5.2,这样的事情应该可以帮助您:

    $startdate = strtotime( '2010/12/24' );
    $enddate = strtotime( '2012/01/05' );
    $loopdate = $startdate;
    $datesArray = array();
    while( $loopdate <= $enddate ) {
       $datesArray[$loopdate] = 0;
       $loopdate = strtotime( '+1 day', $loopdate );
    }
    

    它将创建一个包含开始日期和结束日期之间每个日期的 unix 时间戳的数组作为索引,并将每个值设置为零。然后,您可以使用正确的值覆盖任何实际结果。

    【讨论】:

      【解决方案4】:
      $start_date = DateTime::createFromFormat('Y/m/d', '2010/12/24');
      $end_date = DateTime::createFromFormat('Y/m/d', '2012/01/05');
      
      $current_date = $start_date;
      
      while($current_date <= $end_date) {
          $current_date = $current_date->add(new DateInterval('P1D'));
          // do your array work here.
      }
      

      有关更多信息,请参阅DateTime::add()

      【讨论】:

        【解决方案5】:

        我会以天为单位计算开始日期和结束日期之间的差异,然后在每次迭代的时间戳中添加一天。

        $start = strtotime("2010/12/24");
        $end = strtotime("2012/01/05");
        
        // start and end are seconds, so I convert it to days 
        $diff = ($end - $start) / 86400; 
        
        for ($i = 1; $i < $diff; $i++) {
            // just multiply 86400 and add it to $start
            // using strtotime('+1 day' ...) looks nice but is expensive.
            // you could also have a cumulative value, but this was quicker
            // to type
            $date = $start + ($i * 86400); 
        
            echo date('r', $date);
        }
        

        【讨论】:

        • 老派方法,Mark Ba​​kers 的回答是我认为的首选方法。
        • @TimatMastersAllen 确实如此。他的也是选择的答案。另请注意,您评论的是一个 7 年前的答案。
        • @nikc,org 是的,我知道日期,但您会注意到两个答案的时间相似。不用担心,该评论实际上是针对考虑使用此方法的开发人员,因为它被评论为“完美的答案”,并且今天仍有人使用它。
        • 公平点,但在过去它更流血。 FWIW 我也喜欢使用 DateTime 类(和朋友),但是许多 PHP 托管服务提供商安装了​​古老的 PHP 版本,导致采用更现代的 API 非常缓慢。
        【解决方案6】:

        我保存了这段可怕的代码:

        while (($tmptime = strtotime('+' . (int) $d++ . ' days', strtotime($from))) && ($tmptime <= strtotime($to)))    // this code makes baby jesus cry
            $dates[strftime('%Y-%m-%d', $tmptime)] = 0;
        

        (将 $from$to 设置为适当的值。)它也可能让你哭泣 - 但它有点工作。

        当然,正确的做法是使用DateInterval

        【讨论】:

          猜你喜欢
          • 2015-01-20
          • 2020-01-21
          • 1970-01-01
          • 2020-11-03
          • 1970-01-01
          • 2010-09-13
          • 1970-01-01
          • 1970-01-01
          • 2016-05-06
          相关资源
          最近更新 更多