Tôi có 2 ngày trong PHP, làm thế nào tôi có thể chạy một vòng lặp foreach để trải qua tất cả những ngày đó?


206

Tôi đang bắt đầu với một ngày 2010-05-01và kết thúc bằng 2010-05-10. Làm thế nào tôi có thể lặp qua tất cả những ngày đó trong PHP?

Câu trả lời:


534

Yêu cầu 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");
}

Điều này sẽ xuất ra tất cả các ngày trong khoảng thời gian xác định giữa $start$end. Nếu bạn muốn bao gồm số 10, hãy đặt $endthành thứ 11. Bạn có thể điều chỉnh định dạng theo ý thích của bạn. Xem Hướng dẫn PHP cho DatePeriod .


2
tin tốt - có một bản vá để đặt cờ để bao gồm ngày kết thúc (ngón tay đan chéo) sẽ biến nó thành phiên bản trong tương lai.
chào mừng

8
$begin->setTime(0,0); $end->setTime(12,0);hoặc khởi tạo với thời gian trong ngày của ngày bắt đầu vì bất kỳ lúc nào muộn hơn ngày kết thúc sẽ bao gồm ngày kết thúc trong vòng lặp. Không phải là bản sửa lỗi thời trang nhất, nhưng đó là lựa chọn tốt nhất miễn là không có cờ thích hợp.
Chris

31
Nếu bạn muốn bao gồm ngày kết thúc vào khoảng của mình, bạn có thể làm: $ end = $ end-> sửa đổi ('+1 ngày');
JulienITARD

3
Có thể sử dụng cái này nhưng đảo ngược nó, để lặp lại trong lịch sử?
Jon

3
@JulienITARD đó là một ý tưởng khá hay nhưng thanh lịch hơn sẽ là $ end-> add ($ distance) vì nó phản hồi trực tiếp với một khoảng thay đổi;)
GDY

91

Điều này cũng bao gồm ngày cuối cùng

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

Nếu bạn không cần ngày cuối cùng chỉ cần loại bỏ =khỏi điều kiện.


1
Hãy chắc chắn lưu ý rằng $beginsẽ khác nhau sau vòng lặp. Vòng lặp này sửa đổi đối tượng được tạo bởi new DateTime( "2015-07-03" ). Do đó, tại sao bạn nên sử dụng các phiên bản DateTimeImmutable. Nhưng bạn cần một số sửa đổi thêm cho việc sử dụng chúng.
Henk Poley

39

Chuyển đổi sang dấu thời gian unix làm cho việc thực hiện toán ngày trở nên dễ dàng hơn trong 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
}

Khi sử dụng PHP với múi giờ có DST, hãy đảm bảo thêm thời gian không phải là 23:00, 00:00 hoặc 1:00 để bảo vệ trước những ngày bỏ qua hoặc lặp lại.


4
Tôi không thích vẻ ngoài của 86400. Tôi hiểu rằng đó là 60 * 60 * 24, nhưng vẫn ... một cái gì đó về nó làm tôi khó chịu.
MikeD

13
trong trường hợp này, nó hoạt động, nhưng nếu có sự chuyển đổi giữa thời gian tiết kiệm bình thường và ánh sáng mặt trời, nó sẽ thất bại vì có 90000 ngày thứ hai mà bạn sẽ có hai lần trong vòng lặp của mình ...
oezi

2
Mike, điều tốt nhất để làm là thiết lập một hằng số và đặt tên là "NGÀY" để nó trở nên dễ đọc hơn rất nhiều.
Nhà phát triển Pixel

5
Điều này sẽ bị các vấn đề tiết kiệm ánh sáng ban ngày. Khi bạn vượt qua một điểm thời gian tiết kiệm ánh sáng ban ngày, nó sẽ bị vặn lên. 12:00 sáng không phải là 12:00 sáng ở cả hai phía của thời điểm.
Eric đối thủ

1
Mã này (mỗi mã với 86400 giây mỗi ngày) có vấn đề với việc tiết kiệm ánh sáng ban ngày! Với việc tiết kiệm ánh sáng ban ngày, một số ngày chỉ kéo dài 23 giờ và khoảng 25 giờ.
sbrbot

19

Sao chép từ mẫu php.net cho phạm vi bao gồm :

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

đây là câu trả lời hay nhất và đầy đủ nhất Chỉ thiếu một số giải thích về giá trị DateInterval P1D, vì vậy đây là một số ví dụ về Trình thiết kế giai đoạn Hai ngày: P2D Hai giây: PT2S Một tuần và mười phút: P1WT10M Y trong nhiều năm M trong nhiều tháng D trong nhiều ngày W trong nhiều tuần. Chúng được chuyển đổi thành ngày, do đó không thể kết hợp với D. H trong nhiều giờ M trong vài phút S trong vài giây
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);

hoặc là

$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
Có vẻ như giải pháp này chậm hơn câu trả lời được chấp nhận (chưa chạy một số băng ghế: chậm hơn 100% cho 60 lần lặp). Nhưng tôi chọn cái này để tương thích retro cho các dạng tấm lưu trữ cũ.
Ifnot

7

Đây là một đơn giản -

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

Thí dụ:

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

Sử dụng chức năng này: -

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

Cách sử dụng / chức năng gọi: -

Tăng thêm một ngày: -

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

Tăng theo tháng: -

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

sử dụng tham số thứ ba nếu bạn muốn đặt định dạng ngày: -

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

2

đây là một cách:

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

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

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

     $dtStart->addDay();
 }

Kết quả của $ cuối tuầnInMoth là một loạt các ngày cuối tuần!


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

Bạn cũng có thể lặp lại như thế này, Có $_POST['date']thể là vết lõm từ ứng dụng hoặc trang web của $_POST['date']bạn Thay vì bạn cũng có thể đặt chuỗi của mình ở đây "21-12-2019". Cả hai sẽ làm việc.


0

Nếu bạn sử dụng Laravel và muốn sử dụng Carbon, giải pháp chính xác sẽ là như sau:

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

Nhớ thêm:

  • sử dụng Carbon \ Carbon;
  • sử dụng 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)));
    }

?>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.