PHPに2つの日付がありますが、foreachループを実行してそれらのすべての日を処理するにはどうすればよいですか?


207

私は日付2010-05-01で始まり、で終わり2010-05-10ます。PHPでこれらの日付をすべて反復するにはどうすればよいですか?

回答:


535

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");
}

これは、$startとの間の定義された期間のすべての日を出力します$end。10を含める場合は、$end11 に設定します。好みに合わせてフォーマットを調整できます。DatePeriodのPHPマニュアルを参照してください。


2
良いニュース-(指が交差した)終了日を含むフラグを設定して、それを将来のバージョンにするパッチがあります。
2010

8
$begin->setTime(0,0); $end->setTime(12,0);または、開始日の時刻を終了日の時刻より後の時刻として初期化すると、ループに終了日が含まれます。最もスタイリッシュな修正ではありませんが、適切なフラグがない限り、これは最良のオプションです。
Chris

31
間隔に終了日を含める場合は、次のようにできます。$ end = $ end-> modify( '+1 day');
JulienITARD 2014年

3
これを使用することはできますが、逆にして、履歴をループバックすることはできますか?
ジョン

3
@JulienITARDはかなり良いアイデアですが、変更された間隔に直接応答するため、$ end-> add($ interval)なので、よりエレガントになります;)
GDY

92

これには最後の日付も含まれます

$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");
}

最後の日付が必要ない場合=は、条件から削除してください。


1
ノートに必ず$beginなります異なるループの後に。このループは、によって作成されたオブジェクトを変更しますnew DateTime( "2015-07-03" )。したがって、なぜDateTimeImmutableバージョンを使用する必要があるのですか。ただし、それらを使用するにはさらにいくつかの変更が必要です。
Henk Poley

40

Unixタイムスタンプに変換すると、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
}

DSTのあるタイムゾーンでPHPを使用する場合は、23:00、00:00、1:00以外の時間を追加して、日がスキップしたり繰り返されたりしないようにしてください。


4
私はその86400の外観が好きではありません。それは60 * 60 * 24であると理解していますが、それでも...それについて何かが不愉快です。
MikeD 2010

13
この場合は機能しますが、通常時間と日光節約時間の切り替えがある場合、ループ内に2度ある90000日があるため失敗します...
oezi

2
マイクは、定数を設定して「DAY」という名前を付けるのが一番いいので、ずっと読みやすくなります。
Pixel開発者

5
これは夏時間の問題の影響を受けます。夏時間のポイントを越えると、ねじ込みます。12:00 amは、時点の両側の12:00 amではありません。
エリックコープ

1
このコード(1日あたり86400秒の各コード)には、夏時間の問題があります。夏時間を使用すると、23日しか持続しない日もあれば、25時間かかる日もあります。
sbrbot 2015年

20

php.netのサンプルからコピーして範囲を含めます。

$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>";
}

これが最良かつ最も完全な答えです。DateInterval値P1Dの一部の説明のみが欠落しているので、ここにいくつかの期間指定子の例を示します。これらは日数に変換されるため、Dと組み合わせることはできません。Hは時間でMは分でSは秒で
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);

または

$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);

2
このソリューションは受け入れられた回答よりも遅いようです(一部のベンチを実行していない場合:60回の反復で100%遅い)。しかし、私は古いホスティングプレートフォームのレトロな互換性のためにこれを選択します。
2013年

7

ここに別のシンプルなものがあります-

/**
 * 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;
}

例:

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
)

5

この機能を使用する:-

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

使用法/関数呼び出し:-

1日増やす:-

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

月ごとの増加:-

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

日付形式を設定する場合は、3番目のパラメータを使用します:-

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

2

ここに方法があります:

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

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

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

     $dtStart->addDay();
 }

$ weekendsInMothの結果は、週末の日の配列です!


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"));
}

このように反復することも$_POST['date']できます。アプリやウェブサイトからへこみを付けることができます。$_POST['date']付けることができます"21-12-2019"。ここに文字列を配置することもできます。どちらも機能します。


0

Laravelを使用していてCarbonを使用したい場合、正しい解決策は次のようになります。

$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");
}

追加することを忘れないでください:

  • Carbon \ Carbonを使用します。
  • Carbon \ CarbonPeriodを使用します。

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)));
    }

?>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.