8
votes

Boucle à travers les dates avec php

J'essaie de boucler des dates avec PHP. Actuellement, mon code est bloqué dans une boucle répétée 110307. J'ai besoin du format de date à YymMDD. Voici ce que j'essayais d'utiliser: xxx


2 commentaires

Puis au lieu de Modifier ('+ 1 jour'); par exemple, vous pouvez utiliser la méthode -> Ajouter .


@Itay moav pouvez-vous me donner un exemple de ce que vous entendez par -> Ajouter


4 Réponses :


2
votes

Voici une partie d'un code que j'utilise peut probablement être amélioré, dépend de la version PHP que vous utilisez.

//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


3 commentaires

Wow, c'est un poids lourd superbe.


@Paul Schreiber a lu la chose entière, elle fait partie d'un cadre plus grand / lib. C'est lourd, vous avez raison, car je dois utiliser le même code exactement pour différents cycles (il fait partie d'une calculatrice de répéteur d'événement). Mais ... cela m'a pris moins de temps pour le mettre ici que le moment où il vous a fallu pour l'écrire :-)


Je peux voir ça. Il semble qu'il y ait une grosse perf enflammée pour importer un cadre et allouer / instantiier / détruire n objets.



8
votes

Essayez d'utiliser un horodatage UNIX et d'ajouter 86400 à chaque fois. Ça doit être plus rapide que l'appelant strtotime () code>. Vous pouvez Conversions horodaques de recherche en ligne .

<?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>';  
    }
?>


3 commentaires

Le format de date doit être laissé comme Yymmdd ou au moins, il commencera à être utilisé et doit être utilisé dans mon code.


Vous pouvez faire une conversion rapide à l'extérieur de la boucle, ce qui est mille moins chère (O (1)) que de le faire chaque itération (O (n)).


N'utilisez jamais 86400 secondes pendant une journée en raison de la lumière du jour lorsque la journée a 23 ou 25 heures!



5
votes

strtotime interprète "100227" comme 10:02:27 Aujourd'hui, pas 2010-02-27. Donc, après la première étape, $ check_date (aujourd'hui) est "110307". À toutes les étapes suivantes, "110307" est à nouveau interprétée comme une fois aujourd'hui, donnant aujourd'hui $ check_date comme "110307".

Un truc soigné pour les dates d'itération consiste à profiter de la capacité de MKTime à normaliser les dates , quelque chose comme ceci: xxx


2 commentaires

Je n'ai pas vraiment utilisé le code que vous m'avez donné, mais votre raison du problème m'a aidé à trouver une solution. Merci pour votre aide


L'explication était la partie importante.



3
votes

Voici comment je préfère le faire:

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

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


0 commentaires