I'm starting with a date 2010-05-01
and ending with 2010-05-10
. How can I iterate through all of those dates in PHP?
$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");
}
This will output all days in the defined period between $start
and $end
. If you want to include the 10th, set $end
to 11th. You can adjust format to your liking. See the PHP Manual for DatePeriod. It requires PHP 5.3.
$begin->setTime(0,0); $end->setTime(12,0);
or initializing with the time of day of the start date as any time later than that of the end date will include the end date in the loop. Not the most stylish fix, but it's the best option as long as there's not a proper flag. –
Jemy leap year
example and the trick of issuing the setTime()
to include end date into results set. Gordon thanks for your post and @Jemy for the time trick! –
Flowering This also includes the last 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");
}
If you dont need the last date just remove =
from the condition.
$begin
will be different after the loop. This loop modifies the object created by new DateTime( "2015-07-03" )
. Hence why you ought to use the DateTimeImmutable versions. But you need some further modifications for using them. –
Ably Converting to unix timestamps makes doing date math easier in 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
}
When using PHP with a timezone having DST, make sure to add a time that is not 23:00, 00:00 or 1:00 to protect against days skipping or repeating.
Copy from php.net sample for inclusive range:
$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
constructor's $duration
argument takes the letter P (for period), followed by the duration period represented by an integer value (in our case '1') and then by a period designator (in our case 'D'). Thus, a period duration of 1 day. Refer doc link for further information on using this: php.net/manual/en/dateinterval.construct.php –
Joyann Here is another simple implementation -
/**
* 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;
}
Example:
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
)
$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);
or
$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);
User this function:-
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;
}
Usage / function call:-
Increase by one day:-
dateRange($start, $end); //increment is set to 1 day.
Increase by Month:-
dateRange($start, $end, "+1 month");//increase by one month
use third parameter if you like to set date format:-
dateRange($start, $end, "+1 month", "Y-m-d H:i:s");//increase by one month and format is mysql datetime
For Carbon
users
use Carbon\Carbon;
$startDay = Carbon::parse("2021-08-01");
$endDay= Carbon::parse("2021-08-05");
$period = $startDay->range($endDay, 1, 'day');
When I print the data
[
Carbon\Carbon @1627790400 {#4970
date: 2021-08-01 00:00:00.0 America/Toronto (-04:00),
},
Carbon\Carbon @1627876800 {#4974
date: 2021-08-02 00:00:00.0 America/Toronto (-04:00),
},
Carbon\Carbon @1627963200 {#4978
date: 2021-08-03 00:00:00.0 America/Toronto (-04:00),
},
Carbon\Carbon @1628049600 {#5007
date: 2021-08-04 00:00:00.0 America/Toronto (-04:00),
},
Carbon\Carbon @1628136000 {#5009
date: 2021-08-05 00:00:00.0 America/Toronto (-04:00),
},
]
This is Laravel data dump using dd($period->toArray());
. You can now iterate through $period
if you want with a foreach
statement.
One important note - it includes both the edge dates provided to method.
For more cool date related stuff, do check out the Carbon docs.
here's a way:
$date = new Carbon();
$dtStart = $date->startOfMonth();
$dtEnd = $dtStart->copy()->endOfMonth();
$weekendsInMoth = [];
while ($dtStart->diffInDays($dtEnd)) {
if($dtStart->isWeekend()) {
$weekendsInMoth[] = $dtStart->copy();
}
$dtStart->addDay();
}
The result of $weekendsInMoth is array of weekend days!
If you're using php version less than 8.2 and don't have the DatePeriod::INCLUDE_END_DATE
const. I wrote a method that returns an array of \DateTimeImmutable
.
This works with a start date before, the same or after the end date.
/**
* @param DateTimeImmutable $start
* @param DateTimeImmutable $end
* @return array<\DateTimeImmutable>
*/
public static function getRangeDays(\DateTimeImmutable $start, \DateTimeImmutable $end): array
{
$startDate = $start;
$endDate = $end;
$forwards = $endDate >= $startDate;
$carryDate = $startDate;
$days = [];
while (true) {
if (($forwards && $carryDate > $end) || (!$forwards && $carryDate < $end)) {
break;
}
$days[] = $carryDate;
if ($forwards) {
$carryDate = $carryDate->modify('+1 day');
} else {
$carryDate = $carryDate->modify('- 1 day');
}
}
return $days;
}
Just a thought with the while loop
$startDate = '2023-03-01';
$endDate = '2023-04-01';
$currentDate = strtotime($startDate);
$endDate = strtotime($endDate);
while ($currentDate <= $endDate) {
echo date('Y-m-d', $currentDate) . "\n";
$currentDate = strtotime('+1 day', $currentDate);
}
$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"));
}
You can iterate like this also, The $_POST['date']
can be dent from your app or website
Instead of $_POST['date']
you can also place your string here "21-12-2019"
. Both will work.
<?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)));
}
?>
I like using simple, clean and library-less methods like this:
function datesBetween($startDate, $endDate)
{
$dates = [];
$start = new DateTime($startDate);
$end = new DateTime($endDate);
while ($start <= $end) {
$dates[] = $start->format('Y-m-d');
$start->modify('+1 day');
}
return $dates;
}
Hope it helps someone.
If you use Laravel and want to use Carbon the correct solution would be the following:
$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");
}
Remember to add:
- use Carbon\Carbon;
- use Carbon\CarbonPeriod;
The more elastic example
//dilo surucu
class Day
{
private DateTimeInterface $dateTime;
public function __construct(DateTimeInterface $dateTime)
{
$this->dateTime = $dateTime;
}
public function today(string $format='Y-m-d'): string
{
return $this->dateTime->format($format);
}
public function yesterday(string $format='Y-m-d'): string
{
$today = $this->today();
return date($format, strtotime("$today -1 days"));
}
public function tomorrow(string $format='Y-m-d'): string
{
$today = $this->today();
return date($format, strtotime("$today +1 days"));
}
}
class DayIterator implements Iterator
{
private DateTimeInterface $currentDate;
private DateTimeInterface $endDate;
/**
* @throws Exception
*/
public function __construct(string $startDate, string $endDate)
{
$this->currentDate = new DateTime($startDate);
$this->endDate = new DateTime($endDate);
}
public function current(): Day
{
return new Day($this->currentDate);
}
public function key(): string
{
return $this->currentDate->format('Y-m-d');
}
public function next(): void
{
$this->currentDate = $this->currentDate->add(new DateInterval('P1D'));
}
public function rewind(): void
{
}
public function valid(): bool
{
return $this->currentDate <= $this->endDate;
}
}
// Usage
$dayIterator = new DayIterator(
'2024-01-01',
'2024-01-12'
);
foreach ($dayIterator as $day) {
echo 'Yesterday: ' . $day->yesterday('D Y-m-d') . PHP_EOL;
echo 'Date: ' . $day->today('D Y-m-d D') . PHP_EOL;
echo 'Tomorrow: ' . $day->tomorrow('D Y-m-d') . PHP_EOL;
echo PHP_EOL;
}
© 2022 - 2024 — McMap. All rights reserved.