2011-03-06 22 views
8

Estoy intentando recorrer las fechas con PHP. Actualmente mi código se atasca en un bucle que repite 110307. Necesito que el formato de fecha esté en aammdd. Esto es lo que estaba tratando de usar:Recorra las fechas con PHP

<?php 
    $check_date = '100227'; 
    $end_date = '100324'; 

    while($check_date != $end_date){ 
     $check_date = date("ymd", strtotime("+1 day", strtotime($check_date))); 
     echo $check_date . '<br>'; 
    } 
?> 
+0

¿qué versión de php? –

+0

@Itay Moav: versión 5.2.17. – shinjuo

+0

Luego, en lugar de 'modify ('+ 1 day');' por ejemplo, puede usar el método '-> add'. –

Respuesta

5

strtotime interpreta "100227" como el tiempo 10:02:27 hoy, no 2010-02-27. Entonces, después del primer paso, $check_date (hoy) es "110307". En todos los pasos posteriores, "110307" se interpreta nuevamente como una hora actual, dando $check_date como "110307" nuevamente.

Un buen truco para iterar fechas es tomar ventaja de la capacidad de mktime para normalizar las fechas, algo como esto:

$date_arr = array(27,2,2010); 
$end_date = "100324"; 
do { 
    $check_date = gmdate('ymd', gmmktime(0,0,0,$date_arr[1],$date_arr[0]++,$date_arr[2])); 
    echo $check_date."\n"; 
} while($end_date!=$check_date); 
+0

No usé realmente el código que me diste, pero el motivo del problema me ayudó a encontrar una solución. Gracias por toda la ayuda – shinjuo

+1

La explicación fue la parte importante. – Anomie

2

aquí es parte de un código que utilizo, probablemente se puede mejorar, depende de la versión de PHP que utilice.

//usage 
$Iterator=class Dates_DateIterator::factory('Daily', 
              new Datetime('20100227'), 
              new Datetime('20100324')); 

foreach($Iterator as $i=>$day){ 
    var_dump($i); 
    var_dump($day); 
} 


//code lib 
abstract class Dates_DateIterator implements Iterator 
{ 
    /** 
    * Factory method, saves some code, also enable me to put everything in the same class 
    * as we use Autoload to load classes. 
    */ 
    static public function factory($cycle,DateTime $DateI,DateTime $DateII){ 
     switch($cycle){ 
      case 'Daily': 
       return new DaysIterator($DateI,$DateII); 
      case 'Weekly': 
       return new WeeksIterator($DateI,$DateII); 
      case 'Monthly': 
       return new MonthsIterator($DateI,$DateII); 
      case 'Yearly': 
       return new YearsIterator($DateI,$DateII); 
      default: 
       throw(new Exception('No valid cycle was chosen to iterate over')); 
     } 
    } 
    /** 
    * @var DateTime represents the start range. 
    */ 
    public $FromDate; 
    /** 
    * @var DateTime represents the end range. 
    */ 
    public $ToDate; 
    /** 
    * @var DateTime Current Date. 
    */ 
    protected $CurrentDate; 

    public function __construct(DateTime $DateI,DateTime $DateII) 
    { 
     if($DateII->format('U') > $DateI->format('U')) 
     { 
      $this->FromDate=$DateI; 
      $this->ToDate=$DateII; 
      $this->CurrentDate=$DateI; 
     } 
     else 
     { 
      $this->FromDate=$DateII; 
      $this->ToDate=$DateI; 
      $this->CurrentDate=$DateII; 
     } 
    }//EOF constructor 

    /** 
    * @return DateTime 
    */ 
    public function getClonedCurrent(){ 
     return clone($this->CurrentDate); 
    } 

    public function current() 
    { 
     return $this->CurrentDate; 
    }//EOF current 

    public function currentDate() 
    { 
     return $this->CurrentDate->format('Ymd'); 
    }//EOF current 

    public function rewind() 
    { 
     $this->CurrentDate=$this->FromDate; 
    }//EOF rewind 

    public function valid() 
    { 
     //Kill hours/minutes/seconds. If we are to add hours and minutes iterators, we will need to rethink this. 
     return (floor($this->CurrentDate->format('U')/(3600*24)) <= floor($this->ToDate->format('U')/(3600*24))); 
    }//EOF valid  
}//EOF CLASS DateIterator 









class DaysIterator extends SiTEL_Dates_DateIterator 
{ 
    public function __construct(DateTime $DateI,DateTime $DateII) 
    { 
     parent::__construct($DateI,$DateII); 
    }//EOF constructor 

    public function next() 
    { 
     $this->CurrentDate->modify('+1 day'); 
    }//EOF next 

    public function key() 
    { 
     return $this->CurrentDate->format('d'); 
    }//EOF key 

}//EOD CLASS DaysIterator 
+2

Guau, eso es súper pesado. –

+0

@Paul Schreiber lee todo, es parte de un framework/lib más grande. Es pesado, tienes razón, ya que necesito usar el mismo código exactamente para diferentes ciclos (es parte de una calculadora de repetición de eventos). Pero ... Me tomó menos tiempo ponerlo aquí que el tiempo que tardó en escribirlo :-) –

+0

Puedo ver eso. Parece que hay un gran golpe de perforación para importar un marco y asignar/instanciar/destruir n objetos. –

8

Pruebe usar una marca de tiempo unix y agregue 86400 cada vez. Eso debe ser más rápido que llamar al strtotime(). Puede lookup timestamp conversions online.

<?php 
    $check_date = 1267228800; // '2010-02-27'; 
    $end_date = 1269388800; // '2010-03-24'; 

    while($check_date != $end_date){ 
     $check_date += 86400; 
     echo date("Ymd", $check_date) . '<br>'; 
    } 
?> 
+0

El formato de fecha debe dejarse como aammdd o al menos comenzará como eso y debe usarse en mi código como – shinjuo

+0

Puede hacer una conversión rápida fuera del ciclo, que es mucho más barato (O (1)) que hacerlo cada iteración (O (n)). –

+0

¡Nunca use 86400 segundos por un día debido al horario de verano cuando el día tiene 23 o 25 horas! – sbrbot

3

Así es como yo prefiero hacerlo:

$startDate = new DateTime('20100227'); 
$endDate = new DateTime('20100324'); 

while ($startDate <= $endDate) { 
    // your code here 
    ... 
    // go to the next day 
    $startDate->add(new DateInterval('P1D')); 
} 

Me parece mucho más limpio personalmente, y es bueno no tener que codificar valores como 84600.