【问题标题】:Date manipulation in PHPPHP中的日期操作
【发布时间】:2025-12-05 00:45:01
【问题描述】:

我试图在一个循环中以固定的次数重复一个月的日期。如果日期是有效日期,它只会回显日期,否则它将跳过日期。 例如,如果“2012-02-30 10:10:00”进入循环,它将被忽略并跳过,并继续进行下一次迭代。

以下代码适用于 start_date “2011-11-07 10:15:00”,但是当我将其更改为注释为“2011-11-30 10:15:00”的 start_date 时,它​​会添加 24跳过一次迭代后的几个小时。

我不确定我哪里出错了。

<?php
//$start_date = "2011-11-30 10:15:00";
$start_date = "2011-11-07 10:15:00";
$no_of_repeat = 15;
$repeat_timing = 0;
for($x=0; $x<$no_of_repeat; $x++) {
    $start_date = date('Y-m-d G:i:s',(strtotime($start_date) + ($repeat_timing)));
    if(date("m",strtotime($start_date)) != 12) {
        $next_month = date('m',strtotime($start_date)) + 1;
        $year = date('Y',strtotime($start_date));
    } else {
        $next_month = 1 ;
        $year = date('Y',strtotime($start_date)) + 1;
    }
    $day = date("d",strtotime($start_date));
    $next_date =
    $year."-".
    $next_month."-".
    $day." ".
    date("G",strtotime($start_date)).":".
    date("i",strtotime($start_date)).":".
    date("s",strtotime($start_date));
    if(checkdate($next_month,$day,$year))
        $repeat_timing = strtotime($next_date) - strtotime($start_date);
    else
        continue;   
    echo $next_date."<br />";
}
?>

注释的 start_date 的预期结果如下:

2011-12-30 10:15:00
2012-1-30 10:15:00
2012-3-30 10:15:00
2012-4-30 10:15:00
2012-5-30 10:15:00
2012-6-30 10:15:00
2012-7-30 10:15:00
2012-8-30 10:15:00
2012-9-30 10:15:00
2012-10-30 10:15:00
2012-11-30 10:15:00
2012-12-30 10:15:00
2013-1-30 10:15:00

【问题讨论】:

  • 你展示了预期的结果,但你得到的结果是什么?可以发一下吗?
  • 只需执行上面给出的脚本,取消注释的 start_date 并注释当前的 start_date

标签: php date datetime time date-math


【解决方案1】:

当你打电话时

 $start_date = date('Y-m-d G:i:s',(strtotime($start_date) + ($repeat_timing)));

它在日期上增加了 1 个月,但它也补偿了 repeat_timing 变量。您将 2678400 秒添加到 2011 年 1 月 30 日的日期,这大约相当于 2011 年 3 月 1 日。

最好将月、日和年与日期变量分开并手动进行计算。这将防止 DATE 更改您的时间范围。

【讨论】:

    【解决方案2】:

    尝试以下方法:

    // starting variables
    $startDate = "2011-11-30";
    $time = '10:15:00';
    $numberOfTimesToRepeat = 10;
    
    // Set our counts to 0
    $count = 0;
    $datesFound = 0;
    
    // parse date
    list($startYear,$startMonth,$startDay) = explode('-',$startDate);
    
    // Create an array
    while ($datesFound < $numberOfTimesToRepeat) {
    
        // Calculate number of months to add
        $monthsToAdd = fmod($count,12);
    
        // Calculate new month number
        $newMonth = (($startMonth + $monthsToAdd) > 12) ? ($startMonth + $monthsToAdd - 12) : ($startMonth + $monthsToAdd);
    
        // Add the leading 0 if necessary   
        if ($newMonth < 10 && strlen($newMonth) < 2) $newMonth = '0'.$newMonth;
    
        // Calculate number of months to add
        $yearsToAdd = floor(($count/12));
    
        $newYear = $startYear + $yearsToAdd;
    
        if (checkdate($newMonth,$startDay,$newYear)) {
            $dates[] = $newYear.'-'.$newMonth.'-'.$startDay.' '.$time;
            $datesFound++;
        }
    
        // increase our count either way
        $count++;
    
    }
    
    
    
    // Show the dates
    foreach ($dates as $date) {
        echo $date.'<br />';
    }
    

    【讨论】:

      【解决方案3】:

      这是一个简短的、可信赖的函数,它回显有效的日期时间戳:online demo

      function getValidDateTimes($date,$iterations){
          if(preg_match("/(\d{4})-(\d{1,2})-(\d{2}) (.*)/",$date,$n)){ // capture datetime bits
              list(,$Y,$n,$d,$time)=$n;       // declare bits as variables for readability
              for(++$n,$x=0; $x<$iterations; ++$x,++$n){  // start with month after $start_date
                  $n=($n>12?"1":$n);              // reset to 1 when month exceeds 12
                  $date="$Y-$n-$d";               // build literal new date
                  if($date==date("Y-n-d",strtotime($date))){  // built date versus assumed date
                      echo "$date $time<br>";   // store valid date with concatenated time
                  }
              }
          }
      }
      
      $start_date="2011-11-30 10:15:00";
      $iterations=15;
      
      getValidDateTimes($start_date,$iterations);
      

      输出(根据需要/预期):

      2011-12-30 10:15:00
      2011-1-30 10:15:00
      2011-3-30 10:15:00
      2011-4-30 10:15:00
      2011-5-30 10:15:00
      2011-6-30 10:15:00
      2011-7-30 10:15:00
      2011-8-30 10:15:00
      2011-9-30 10:15:00
      2011-10-30 10:15:00
      2011-11-30 10:15:00
      2011-12-30 10:15:00
      2011-1-30 10:15:00
      

      【讨论】:

      • @NikhilRao 如果您认为这是列表中的最佳答案,请给它打上绿色勾号,以便您的问题从未回答的问题列表中删除。如果有什么不对的地方,请告诉我,我会调整的。