J'ai 2 dates en PHP, comment puis-je exécuter une boucle foreach pour passer par tous ces jours?

207

Je commence par une date 2010-05-01et je finis par 2010-05-10. Comment puis-je parcourir toutes ces dates en PHP?

Shamoon
la source

Réponses:

535

Nécessite PHP5.3:

$begin = new DateTime('2010-05-01');
$end = new DateTime('2010-05-10');

$interval = DateInterval::createFromDateString('1 day');
$period = new DatePeriod($begin, $interval, $end);

foreach ($period as $dt) {
    echo $dt->format("l Y-m-d H:i:s\n");
}

Cela produira tous les jours dans la période définie entre $startet $end. Si vous souhaitez inclure le 10, définissez $endle 11. Vous pouvez ajuster le format à votre convenance. Voir le manuel PHP pour DatePeriod .

Gordon
la source
2
bonne nouvelle - il y a un patch pour définir un drapeau pour inclure la date de fin qui (les doigts croisés) en fera une future version.
salathe
8
$begin->setTime(0,0); $end->setTime(12,0);ou l'initialisation avec l'heure de la date de début, car toute heure postérieure à celle de la date de fin inclura la date de fin dans la boucle. Ce n'est pas la solution la plus élégante, mais c'est la meilleure option tant qu'il n'y a pas de drapeau approprié.
Chris
31
Si vous souhaitez inclure la date de fin à votre intervalle, vous pouvez faire: $ end = $ end-> modifier ('+1 jour');
JulienITARD
3
Est-il possible de l'utiliser mais de l'inverser, de revenir en arrière dans l'histoire?
Jon
3
@JulienITARD c'est une assez bonne idée mais plus élégante serait $ end-> add ($ interval) car elle répond directement à un intervalle modifié;)
GDY
92

Cela inclut également la dernière date

$begin = new DateTime( "2015-07-03" );
$end   = new DateTime( "2015-07-09" );

for($i = $begin; $i <= $end; $i->modify('+1 day')){
    echo $i->format("Y-m-d");
}

Si vous n'avez pas besoin de la dernière date, supprimez simplement =la condition.

Sabri Aziri
la source
1
Assurez-vous de noter que ce $beginsera différent après la boucle. Cette boucle modifie l'objet créé par new DateTime( "2015-07-03" ). C'est pourquoi vous devez utiliser les versions DateTimeImmutable. Mais vous avez besoin de modifications supplémentaires pour les utiliser.
Henk Poley
40

La conversion en horodatages Unix facilite les calculs de date en php:

$startTime = strtotime( '2010-05-01 12:00' );
$endTime = strtotime( '2010-05-10 12:00' );

// Loop between timestamps, 24 hours at a time
for ( $i = $startTime; $i <= $endTime; $i = $i + 86400 ) {
  $thisDate = date( 'Y-m-d', $i ); // 2010-05-01, 2010-05-02, etc
}

Lorsque vous utilisez PHP avec un fuseau horaire ayant DST, assurez-vous d'ajouter une heure qui n'est pas 23h00, 00h00 ou 1h00 pour vous protéger contre les jours qui sautent ou se répètent.

Harold1983-
la source
4
Je n'aime pas le look de ce 86400. Je comprends que c'est 60 * 60 * 24, mais quand même ... quelque chose me contrarie.
MikeD
13
dans ce cas, cela fonctionne, mais s'il y a un basculement entre l'heure normale et l'heure d'été, il échouera car il y a un 90000 deuxième jour que vous aurez deux fois dans votre boucle ...
oezi
2
Mike, la meilleure chose à faire est de configurer une constante et de la nommer "JOUR" afin qu'elle devienne beaucoup plus facile à lire.
The Pixel Developer
5
Cela souffrira de problèmes d'heure d'été. Lorsque vous traversez un point d'heure d'été, il se gâche. 12:00 am n'est pas 12:00 am des deux côtés du point dans le temps.
Eric Cope
1
Ce code (chaque code avec 86400 secondes par jour) a un problème avec l'heure d'été! Avec l'heure d'été, certains jours ne durent que 23 heures et environ 25 heures.
sbrbot
20

Copiez à partir de l'exemple php.net pour une plage inclusive :

$begin = new DateTime( '2012-08-01' );
$end = new DateTime( '2012-08-31' );
$end = $end->modify( '+1 day' ); 

$interval = new DateInterval('P1D');
$daterange = new DatePeriod($begin, $interval ,$end);

foreach($daterange as $date){
    echo $date->format("Ymd") . "<br>";
}
Alexander Kharchenko
la source
c'est la meilleure et la plus complète des réponses. Il ne manque qu'une explication de la valeur DateInterval P1D, voici donc quelques exemples de désignateur de période Deux jours: P2D Deux secondes: PT2S Une semaine et dix minutes: P1WT10M Y pour les années M pendant les mois D pour les jours W pour les semaines. Ceux-ci sont convertis en jours, donc ne peuvent pas être combinés avec D. H pendant les heures M pendant les minutes S pendant les secondes
Orcra
15
$startTime = strtotime('2010-05-01'); 
$endTime = strtotime('2010-05-10'); 

// Loop between timestamps, 1 day at a time 
$i = 1;
do {
   $newTime = strtotime('+'.$i++.' days',$startTime); 
   echo $newTime;
} while ($newTime < $endTime);

ou

$startTime = strtotime('2010-05-01'); 
$endTime = strtotime('2010-05-10'); 

// Loop between timestamps, 1 day at a time 
do {
   $startTime = strtotime('+1 day',$startTime); 
   echo $startTime;
} while ($startTime < $endTime);
Mark Baker
la source
2
Il semble que cette solution soit plus lente que la réponse acceptée (non exécuté sur certains bancs: 100% plus lent pour 60 itérations). Mais j'ai choisi celui-ci pour une compatibilité rétro avec les anciennes plateformes d'hébergement.
Ifnot
7

Voici un autre simple -

/**
 * Date range
 *
 * @param $first
 * @param $last
 * @param string $step
 * @param string $format
 * @return array
 */
function dateRange( $first, $last, $step = '+1 day', $format = 'Y-m-d' ) {
    $dates = [];
    $current = strtotime( $first );
    $last = strtotime( $last );

    while( $current <= $last ) {

        $dates[] = date( $format, $current );
        $current = strtotime( $step, $current );
    }

    return $dates;
}

Exemple:

print_r( dateRange( '2010-07-26', '2010-08-05') );

Array (
    [0] => 2010-07-26
    [1] => 2010-07-27
    [2] => 2010-07-28
    [3] => 2010-07-29
    [4] => 2010-07-30
    [5] => 2010-07-31
    [6] => 2010-08-01
    [7] => 2010-08-02
    [8] => 2010-08-03
    [9] => 2010-08-04
    [10] => 2010-08-05
)
HADI
la source
5

Utilisez cette fonction: -

function dateRange($first, $last, $step = '+1 day', $format = 'Y-m-d' ) {
                $dates = array();
                $current = strtotime($first);
                $last = strtotime($last);

                while( $current <= $last ) {    
                    $dates[] = date($format, $current);
                    $current = strtotime($step, $current);
                }
                return $dates;
        }

Utilisation / appel de fonction: -

Augmenter d'un jour: -

dateRange($start, $end); //increment is set to 1 day.

Augmenter par mois: -

dateRange($start, $end, "+1 month");//increase by one month

utilisez le troisième paramètre si vous souhaitez définir le format de la date: -

   dateRange($start, $end, "+1 month", "Y-m-d H:i:s");//increase by one month and format is mysql datetime
user2182143
la source
2

voici un moyen:

 $date = new Carbon();
 $dtStart = $date->startOfMonth();
 $dtEnd = $dtStart->copy()->endOfMonth();

 $weekendsInMoth = [];
 while ($dtStart->diffInDays($dtEnd)) {

     if($dtStart->isWeekend()) {
            $weekendsInMoth[] = $dtStart->copy();
     }

     $dtStart->addDay();
 }

Le résultat de $ weekendsInMoth est une série de jours de week-end!

Jean Souza
la source
0
$date = new DateTime($_POST['date']);
$endDate = date_add(new DateTime($_POST['date']),date_interval_create_from_date_string("7 days"));

while ($date <= $endDate) {
    print date_format($date,'d-m-Y')." AND END DATE IS : ".date_format($endDate,'d-m-Y')."\n";
    date_add($date,date_interval_create_from_date_string("1 days"));
}

Vous pouvez également effectuer une itération comme celle-ci, La $_POST['date']peut être bosselée depuis votre application ou votre site Web. Au lieu de cela, $_POST['date']vous pouvez également placer votre chaîne ici "21-12-2019". Les deux fonctionneront.

zukayu
la source
0

Si vous utilisez Laravel et souhaitez utiliser Carbon, la solution correcte serait la suivante:

$start_date = Carbon::createFromFormat('Y-m-d', '2020-01-01');
$end_date = Carbon::createFromFormat('Y-m-d', '2020-01-31');

$period = new CarbonPeriod($start_date, '1 day', $end_date);

foreach ($period as $dt) {
 echo $dt->format("l Y-m-d H:i:s\n");
}

N'oubliez pas d'ajouter:

  • utiliser Carbon \ Carbon;
  • utiliser Carbon \ CarbonPeriod;
Victor Nuñez
la source
0
<?php

    $start_date = '2015-01-01';
    $end_date = '2015-06-30';

    while (strtotime($start_date) <= strtotime($end_date)) {
        echo "$start_daten";
        $start_date = date ("Y-m-d", strtotime("+1 days", strtotime($start_date)));
    }

?>
Soteris 92
la source