This question already has answers here:
I have 2 dates in PHP, how can I run a foreach loop to go through all of those days?
(13 answers)
Closed 4 years ago.
Expected Input:
getDatesFromRange( '2010-10-01', '2010-10-05' );
Expected Output:
Array( '2010-10-01', '2010-10-02', '2010-10-03', '2010-10-04', '2010-10-05' )
You could also take a look at the DatePeriod class:
$period = new DatePeriod(
new DateTime('2010-10-01'),
new DateInterval('P1D'),
new DateTime('2010-10-05')
);
Which should get you an array with DateTime objects.
To iterate
foreach ($period as $key => $value) {
//$value->format('Y-m-d')
}
function createDateRangeArray($strDateFrom,$strDateTo)
{
// takes two dates formatted as YYYY-MM-DD and creates an
// inclusive array of the dates between the from and to dates.
// could test validity of dates here but I'm already doing
// that in the main script
$aryRange = [];
$iDateFrom = mktime(1, 0, 0, substr($strDateFrom, 5, 2), substr($strDateFrom, 8, 2), substr($strDateFrom, 0, 4));
$iDateTo = mktime(1, 0, 0, substr($strDateTo, 5, 2), substr($strDateTo, 8, 2), substr($strDateTo, 0, 4));
if ($iDateTo >= $iDateFrom) {
array_push($aryRange, date('Y-m-d', $iDateFrom)); // first entry
while ($iDateFrom<$iDateTo) {
$iDateFrom += 86400; // add 24 hours
array_push($aryRange, date('Y-m-d', $iDateFrom));
}
}
return $aryRange;
}
source: http://boonedocks.net/mike/archives/137-Creating-a-Date-Range-Array-with-PHP.html
This is very very flexible.
/**
* Creating date collection between two dates
*
* <code>
* <?php
* # Example 1
* date_range("2014-01-01", "2014-01-20", "+1 day", "m/d/Y");
*
* # Example 2. you can use even time
* date_range("01:00:00", "23:00:00", "+1 hour", "H:i:s");
* </code>
*
* #author Ali OYGUR <alioygur#gmail.com>
* #param string since any date, time or datetime format
* #param string until any date, time or datetime format
* #param string step
* #param string date of output format
* #return array
*/
function date_range($first, $last, $step = '+1 day', $output_format = 'd/m/Y' ) {
$dates = array();
$current = strtotime($first);
$last = strtotime($last);
while( $current <= $last ) {
$dates[] = date($output_format, $current);
$current = strtotime($step, $current);
}
return $dates;
}
Note that the answer provided by ViNce does NOT include the end date for the period.
If you are using PHP 5.3+, your best bet is to use a function like this:
/**
* Generate an array of string dates between 2 dates
*
* #param string $start Start date
* #param string $end End date
* #param string $format Output format (Default: Y-m-d)
*
* #return array
*/
function getDatesFromRange($start, $end, $format = 'Y-m-d') {
$array = array();
$interval = new DateInterval('P1D');
$realEnd = new DateTime($end);
$realEnd->add($interval);
$period = new DatePeriod(new DateTime($start), $interval, $realEnd);
foreach($period as $date) {
$array[] = $date->format($format);
}
return $array;
}
Then, you would call the function as expected:
getDatesFromRange('2010-10-01', '2010-10-05');
Run demo
Note about DatePeriod class: You can use the 4th parameter of DatePeriod to exclude the start date (DatePeriod::EXCLUDE_START_DATE) but you cannot, at this time, include the end date.
Simple but like a charm:
$period = new DatePeriod(new DateTime('2015-01-01'), new DateInterval('P1D'), new DateTime('2015-01-15 +1 day'));
foreach ($period as $date) {
$dates[] = $date->format("Y-m-d");
}
//ONLY SHOWING
echo '<pre>';
var_dump($dates);
echo '</pre>';
exit();
function GetDays($sStartDate, $sEndDate){
// Firstly, format the provided dates.
// This function works best with YYYY-MM-DD
// but other date formats will work thanks
// to strtotime().
$sStartDate = gmdate("Y-m-d", strtotime($sStartDate));
$sEndDate = gmdate("Y-m-d", strtotime($sEndDate));
// Start the variable off with the start date
$aDays[] = $sStartDate;
// Set a 'temp' variable, sCurrentDate, with
// the start date - before beginning the loop
$sCurrentDate = $sStartDate;
// While the current date is less than the end date
while($sCurrentDate < $sEndDate){
// Add a day to the current date
$sCurrentDate = gmdate("Y-m-d", strtotime("+1 day", strtotime($sCurrentDate)));
// Add this new day to the aDays array
$aDays[] = $sCurrentDate;
}
// Once the loop has finished, return the
// array of days.
return $aDays;
}
use like
GetDays('2007-01-01', '2007-01-31');
You must add $end->modify('+1 day') to include last day of interval, for example the January will have a 31 days instead of 30 without using modify() method.
This version of code will include the last day of the interval:
$begin = new DateTime( '2018-08-01' );
$end = new DateTime( '2018-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>";
}
PHP doc link
This is short, sweet, and should work in PHP4+.
function getDatesFromRange($start, $end){
$dates = array($start);
while(end($dates) < $end){
$dates[] = date('Y-m-d', strtotime(end($dates).' +1 day'));
}
return $dates;
}
Short function. PHP 5.3 and up. Can take optional third param of any date format that strtotime can understand. Automatically reverses direction if end < start.
function getDatesFromRange($start, $end, $format='Y-m-d') {
return array_map(function($timestamp) use($format) {
return date($format, $timestamp);
},
range(strtotime($start) + ($start < $end ? 4000 : 8000), strtotime($end) + ($start < $end ? 8000 : 4000), 86400));
}
Test:
date_default_timezone_set('Europe/Berlin');
print_r(getDatesFromRange( '2016-7-28','2016-8-2' ));
print_r(getDatesFromRange( '2016-8-2','2016-7-28' ));
print_r(getDatesFromRange( '2016-10-28','2016-11-2' ));
print_r(getDatesFromRange( '2016-11-2','2016-10-28' ));
print_r(getDatesFromRange( '2016-4-2','2016-3-25' ));
print_r(getDatesFromRange( '2016-3-25','2016-4-2' ));
print_r(getDatesFromRange( '2016-8-2','2016-7-25' ));
print_r(getDatesFromRange( '2016-7-25','2016-8-2' ));
Output:
Array ( [0] => 2016-07-28 [1] => 2016-07-29 [2] => 2016-07-30 [3] => 2016-07-31 [4] => 2016-08-01 [5] => 2016-08-02 )
Array ( [0] => 2016-08-02 [1] => 2016-08-01 [2] => 2016-07-31 [3] => 2016-07-30 [4] => 2016-07-29 [5] => 2016-07-28 )
Array ( [0] => 2016-10-28 [1] => 2016-10-29 [2] => 2016-10-30 [3] => 2016-10-31 [4] => 2016-11-01 [5] => 2016-11-02 )
Array ( [0] => 2016-11-02 [1] => 2016-11-01 [2] => 2016-10-31 [3] => 2016-10-30 [4] => 2016-10-29 [5] => 2016-10-28 )
Array ( [0] => 2016-04-02 [1] => 2016-04-01 [2] => 2016-03-31 [3] => 2016-03-30 [4] => 2016-03-29 [5] => 2016-03-28 [6] => 2016-03-27 [7] => 2016-03-26 [8] => 2016-03-25 )
Array ( [0] => 2016-03-25 [1] => 2016-03-26 [2] => 2016-03-27 [3] => 2016-03-28 [4] => 2016-03-29 [5] => 2016-03-30 [6] => 2016-03-31 [7] => 2016-04-01 [8] => 2016-04-02 )
Array ( [0] => 2016-08-02 [1] => 2016-08-01 [2] => 2016-07-31 [3] => 2016-07-30 [4] => 2016-07-29 [5] => 2016-07-28 [6] => 2016-07-27 [7] => 2016-07-26 [8] => 2016-07-25 )
Array ( [0] => 2016-07-25 [1] => 2016-07-26 [2] => 2016-07-27 [3] => 2016-07-28 [4] => 2016-07-29 [5] => 2016-07-30 [6] => 2016-07-31 [7] => 2016-08-01 [8] => 2016-08-02 )
Here is a function, that will return date ranges in both directions and it works on PHP >=5.2.2 :
function createRange($start, $end, $format = 'Y-m-d') {
$start = new DateTime($start);
$end = new DateTime($end);
$invert = $start > $end;
$dates = array();
$dates[] = $start->format($format);
while ($start != $end) {
$start->modify(($invert ? '-' : '+') . '1 day');
$dates[] = $start->format($format);
}
return $dates;
}
Use example:
print_r(createRange('2010-10-01', '2010-10-05'));
/*Array
(
[0] => 2010-10-01
[1] => 2010-10-02
[2] => 2010-10-03
[3] => 2010-10-04
[4] => 2010-10-05
)*/
print_r(createRange('2010-10-05', '2010-10-01', 'j M Y'));
/*Array
(
[0] => 5 Oct 2010
[1] => 4 Oct 2010
[2] => 3 Oct 2010
[3] => 2 Oct 2010
[4] => 1 Oct 2010
)*/
demo
many ways of getting this done, but finally it all depends on PHP version you are using. Here is summary of all solutions:
get PHP version:
echo phpinfo();
PHP 5.3+
$period = new DatePeriod(
new DateTime('2010-10-01'),
new DateInterval('P1D'),
new DateTime('2010-10-05')
);
PHP 4+
/**
* creating between two date
* #param string since
* #param string until
* #param string step
* #param string date format
* #return array
* #author Ali OYGUR <alioygur#gmail.com>
*/
function dateRange($first, $last, $step = '+1 day', $format = 'd/m/Y' ) {
$dates = array();
$current = strtotime($first);
$last = strtotime($last);
while( $current <= $last ) {
$dates[] = date($format, $current);
$current = strtotime($step, $current);
}
return $dates;
}
PHP < 4
you should upgrade :)
// Specify the start date. This date can be any English textual format
$date_from = "2018-02-03";
$date_from = strtotime($date_from); // Convert date to a UNIX timestamp
// Specify the end date. This date can be any English textual format
$date_to = "2018-09-10";
$date_to = strtotime($date_to); // Convert date to a UNIX timestamp
// Loop from the start date to end date and output all dates inbetween
for ($i=$date_from; $i<=$date_to; $i+=86400) {
echo date("Y-m-d", $i).'<br />';
}
<?
print_r(getDatesFromRange( '2010-10-01', '2010-10-05' ));
function getDatesFromRange($startDate, $endDate)
{
$return = array($startDate);
$start = $startDate;
$i=1;
if (strtotime($startDate) < strtotime($endDate))
{
while (strtotime($start) < strtotime($endDate))
{
$start = date('Y-m-d', strtotime($startDate.'+'.$i.' days'));
$return[] = $start;
$i++;
}
}
return $return;
}
Solution for PHP 5.2 with DateTime objects. But startDate MUST be before endDate.
function createRange($startDate, $endDate) {
$tmpDate = new DateTime($startDate);
$tmpEndDate = new DateTime($endDate);
$outArray = array();
do {
$outArray[] = $tmpDate->format('Y-m-d');
} while ($tmpDate->modify('+1 day') <= $tmpEndDate);
return $outArray;
}
Using:
$dates = createRange('2010-10-01', '2010-10-05');
$dates contain:
Array( '2010-10-01', '2010-10-02', '2010-10-03', '2010-10-04', '2010-10-05' )
function createDateRangeArray($start, $end) {
// Modified by JJ Geewax
$range = array();
if (is_string($start) === true) $start = strtotime($start);
if (is_string($end) === true ) $end = strtotime($end);
if ($start > $end) return createDateRangeArray($end, $start);
do {
$range[] = date('Y-m-d', $start);
$start = strtotime("+ 1 day", $start);
}
while($start < $end);
return $range;
}
Source: http://boonedocks.net/mike/archives/137-Creating-a-Date-Range-Array-with-PHP.html
$report_starting_date=date('2014-09-16');
$report_ending_date=date('2014-09-26');
$report_starting_date1=date('Y-m-d',strtotime($report_starting_date.'-1 day'));
while (strtotime($report_starting_date1)<strtotime($report_ending_date))
{
$report_starting_date1=date('Y-m-d',strtotime($report_starting_date1.'+1 day'));
$dates[]=$report_starting_date1;
}
print_r($dates);
// dates ('2014-09-16', '2014-09-26')
//print result Array
(
[0] => 2014-09-16
[1] => 2014-09-17
[2] => 2014-09-18
[3] => 2014-09-19
[4] => 2014-09-20
[5] => 2014-09-21
[6] => 2014-09-22
[7] => 2014-09-23
[8] => 2014-09-24
[9] => 2014-09-25
[10] => 2014-09-26
)
Here's a way of doing this using Carbon https://github.com/briannesbitt/Carbon:
public function buildDateRangeArray($first, $last)
{
while ($first <= $last) {
$dates[] = $first->toDateString();
$first->addDay();
}
return $dates;
}
This, of course, can be tweaked to not use Carbon. The $first and $last parameters passed to the function are Carbon instances.
// will return dates array
function returnBetweenDates( $startDate, $endDate ){
$startStamp = strtotime( $startDate );
$endStamp = strtotime( $endDate );
if( $endStamp > $startStamp ){
while( $endStamp >= $startStamp ){
$dateArr[] = date( 'Y-m-d', $startStamp );
$startStamp = strtotime( ' +1 day ', $startStamp );
}
return $dateArr;
}else{
return $startDate;
}
}
returnBetweenDates( '2014-09-16', '2014-09-26' );
// print_r( returnBetweenDates( '2014-09-16', '2014-09-26' ) );
it will return array like below:
Array
(
[0] => 2014-09-16
[1] => 2014-09-17
[2] => 2014-09-18
[3] => 2014-09-19
[4] => 2014-09-20
[5] => 2014-09-21
[6] => 2014-09-22
[7] => 2014-09-23
[8] => 2014-09-24
[9] => 2014-09-25
[10] => 2014-09-26
)
I think it's the shortest answer
Edit the code as you like
for ($x=strtotime('2015-12-01');$x<=strtotime('2015-12-30');$x+=86400)
echo date('Y-m-d',$x);
I love a solid one-liner!
My php discovery of the day was that array_push() returns the new number of elements in the array.
I managed to check for the end date match, increment $x, and push new elements all within the two-part condition statement of an empty while loop.
function getDatesFromRange($a,$b,$x=0,$dates=[]){
while(end($dates)!=$b && $x=array_push($dates,date("Y-m-d",strtotime("$a +$x day"))));
return $dates;
}
var_export(getDatesFromRange('2010-10-01','2010-10-05'));
The most similar function to mine on this page is drolex's (which I didn't actually find until after I wrote mine, if you believe me). I did some speed tests across large and small date ranges and they seem to beat each other just as often -- so I'm calling them equal performers. Here are some other comparisons:
We both use date(), strtotime(), and two array functions.
Drolex uses just three variables, I use the same three plus $x.
Because loading the start date into the $date array is not necessary for my function, I can declare it in the function parameters and spare the line (likewise with $x).
**Just a couple of important notes:
1- Date strings MUST BE validated before being fed to the function.
2- The above function can only handle forward moving date ranges.
If you want backward moving date ranges, simply reverse the date order in the function call and add a minus after $x=. (Pretty slick, eh?)
function getDatesFromRange($a,$b,$x=0,$dates=[]){
while(end($dates)!=$b && $x=-array_push($dates,date("Y-m-d",strtotime("$a +$x day"))));
return $dates;
}
var_export(getDatesFromRange('2010-10-05','2010-10-01'));
One more extension/consideration...
Imagine you have a multi-cultural (or sloppy) user base, and your function MUST be able to receive start and end dates in different valid formats AND you need to be able to output the array in any of the valid formats? By minor adjustment, I've provided a solution for that.
By "valid" I mean YYYY-MM-DD, MM/DD/YYY, and DD-MM-YYYY, these are massively popular standards world-wide, if another format is necessary then usability would come down to strtotime's comprehension of it.
Here is the Demo.
Code:
function getDatesFromRange($a,$b,$format='Y-m-d',$dates=[],$x=0){
while(date($format,strtotime(end($dates)))!=date($format,strtotime($b)) && $x=array_push($dates,date($format,strtotime("$a +$x day"))));
return $dates;
}
$formats=array("Computer"=>'Y-m-d',"American"=>'m/d/Y','Non-American'=>'d-m-Y');
$start='15-02-2017'; // Non-American formatted start date
$end='2017-02-27'; // Computer formatted start date
foreach($formats as $label=>$format){
echo "<br>$label<br>";
var_export(getDatesFromRange($start,$end,$format));
echo "<br>";
}
Output
Computer
array ( 0 => '2017-02-15', 1 => '2017-02-16', 2 => '2017-02-17', 3 => '2017-02-18',
4 => '2017-02-19', 5 => '2017-02-20', 6 => '2017-02-21', 7 => '2017-02-22',
8 => '2017-02-23', 9 => '2017-02-24', 10 => '2017-02-25', 11 => '2017-02-26',
12 => '2017-02-27', )
American
array ( 0 => '02/15/2017', 1 => '02/16/2017', 2 => '02/17/2017', 3 => '02/18/2017',
4 => '02/19/2017', 5 => '02/20/2017', 6 => '02/21/2017', 7 => '02/22/2017',
8 => '02/23/2017', 9 => '02/24/2017', 10 => '02/25/2017', 11 => '02/26/2017',
12 => '02/27/2017', )
Non-American
array ( 0 => '15-02-2017', 1 => '16-02-2017', 2 => '17-02-2017', 3 => '18-02-2017',
4 => '19-02-2017', 5 => '20-02-2017', 6 => '21-02-2017', 7 => '22-02-2017',
8 => '23-02-2017', 9 => '24-02-2017', 10 => '25-02-2017', 11 => '26-02-2017',
12 => '27-02-2017', )
Now some people don't 100% trust strtotime() because of some buggy behaviors. I think I've read that it will foul up when trying to jump a month from a leap-day. However, unless someone can reproduce it to prove me wrong, strtotime() is never going to let you down when you are only incrementing by one day.
Here is the another solution. Please check this.
$first = '10/30/2017'; //starting date
$last= '10/11/2017'; //ending date
$first_time_arr=explode('/',$first);
$last_time_arr=explode('/',$last);
//create timestamp of starting date
$start_timestamp=mktime(0,0,0, $first_time_arr[0], $first_time_arr[1],$first_time_arr[2]);
//create timestamp of ending date
$end_timestamp=mktime(0,0,0, $last_time_arr[0], $last_time_arr[1],$last_time_arr[2]);
$date_arr=array();
for($i=$start_timestamp;$i<=$end_timestamp;$i=$i+86400){
$date_arr[]=date("Y-m-d",$i); //this will save all dates in array
}
public static function countDays($date1,$date2)
{
$date1 = strtotime($date1); // or your date as well
$date2 = strtotime($date2);
$datediff = $date1 - $date2;
return floor($datediff/(60*60*24));
}
public static function dateRange($date1,$date2)
{
$count = static::countDays($date1,$date2) + 1;
$dates = array();
for($i=0;$i<$count;$i++)
{
$dates[] = date("Y-m-d",strtotime($date2.'+'.$i.' days'));
}
return $dates;
}
function datesbetween ($date1,$date2)
{
$dates= array();
for ($i = $date1
; $i<= $date1
; $i=date_add($i, date_interval_create_from_date_string('1 days')) )
{
$dates[] = clone $i;
}
return $dates;
}
To make Mostafa's answer complete, this is definietly the simplest and most efficient way to do it:
function getDatesFromRange($start_date, $end_date, $date_format = 'Y-m-d')
{
$dates_array = array();
for ($x = strtotime($start_date); $x <= strtotime($end_date); $x += 86400) {
array_push($dates_array, date($date_format, $x));
}
return $dates_array;
}
// see the dates in the array
print_r( getDatesFromRange('2017-02-09', '2017-02-19') );
You can even change the default output date format if you add a third parameter when you call the function, otherwise it will use the default format that's been set as 'Y-m-d'.
I hope it helps :)
function getWeekdayDatesFrom($format, $start_date_epoch, $end_date_epoch, $range) {
$dates_arr = array();
if( ! $range) {
$range = round(abs($start_date_epoch-$end_date_epoch)/86400) + 1;
} else {
$range = $range + 1; //end date inclusive
}
$current_date_epoch = $start_date_epoch;
for($i = 1; $i <= $range; $i+1) {
$d = date('N', $current_date_epoch);
if($d <= 5) { // not sat or sun
$dates_arr[] = "'".date($format, $current_date_epoch)."'";
}
$next_day_epoch = strtotime('+'.$i.'day', $start_date_epoch);
$i++;
$current_date_epoch = $next_day_epoch;
}
return $dates_arr;
}
$arr = range(strtotime("2013-12-01"),strtotime("2013-12-31"), "86400");
array_walk_recursive($arr, function(&$element) { $element = date("Y-m-d", $element); });
print_r ($arr);
Related
This question already has answers here:
I have 2 dates in PHP, how can I run a foreach loop to go through all of those days?
(13 answers)
Closed 4 years ago.
Expected Input:
getDatesFromRange( '2010-10-01', '2010-10-05' );
Expected Output:
Array( '2010-10-01', '2010-10-02', '2010-10-03', '2010-10-04', '2010-10-05' )
You could also take a look at the DatePeriod class:
$period = new DatePeriod(
new DateTime('2010-10-01'),
new DateInterval('P1D'),
new DateTime('2010-10-05')
);
Which should get you an array with DateTime objects.
To iterate
foreach ($period as $key => $value) {
//$value->format('Y-m-d')
}
function createDateRangeArray($strDateFrom,$strDateTo)
{
// takes two dates formatted as YYYY-MM-DD and creates an
// inclusive array of the dates between the from and to dates.
// could test validity of dates here but I'm already doing
// that in the main script
$aryRange = [];
$iDateFrom = mktime(1, 0, 0, substr($strDateFrom, 5, 2), substr($strDateFrom, 8, 2), substr($strDateFrom, 0, 4));
$iDateTo = mktime(1, 0, 0, substr($strDateTo, 5, 2), substr($strDateTo, 8, 2), substr($strDateTo, 0, 4));
if ($iDateTo >= $iDateFrom) {
array_push($aryRange, date('Y-m-d', $iDateFrom)); // first entry
while ($iDateFrom<$iDateTo) {
$iDateFrom += 86400; // add 24 hours
array_push($aryRange, date('Y-m-d', $iDateFrom));
}
}
return $aryRange;
}
source: http://boonedocks.net/mike/archives/137-Creating-a-Date-Range-Array-with-PHP.html
This is very very flexible.
/**
* Creating date collection between two dates
*
* <code>
* <?php
* # Example 1
* date_range("2014-01-01", "2014-01-20", "+1 day", "m/d/Y");
*
* # Example 2. you can use even time
* date_range("01:00:00", "23:00:00", "+1 hour", "H:i:s");
* </code>
*
* #author Ali OYGUR <alioygur#gmail.com>
* #param string since any date, time or datetime format
* #param string until any date, time or datetime format
* #param string step
* #param string date of output format
* #return array
*/
function date_range($first, $last, $step = '+1 day', $output_format = 'd/m/Y' ) {
$dates = array();
$current = strtotime($first);
$last = strtotime($last);
while( $current <= $last ) {
$dates[] = date($output_format, $current);
$current = strtotime($step, $current);
}
return $dates;
}
Note that the answer provided by ViNce does NOT include the end date for the period.
If you are using PHP 5.3+, your best bet is to use a function like this:
/**
* Generate an array of string dates between 2 dates
*
* #param string $start Start date
* #param string $end End date
* #param string $format Output format (Default: Y-m-d)
*
* #return array
*/
function getDatesFromRange($start, $end, $format = 'Y-m-d') {
$array = array();
$interval = new DateInterval('P1D');
$realEnd = new DateTime($end);
$realEnd->add($interval);
$period = new DatePeriod(new DateTime($start), $interval, $realEnd);
foreach($period as $date) {
$array[] = $date->format($format);
}
return $array;
}
Then, you would call the function as expected:
getDatesFromRange('2010-10-01', '2010-10-05');
Run demo
Note about DatePeriod class: You can use the 4th parameter of DatePeriod to exclude the start date (DatePeriod::EXCLUDE_START_DATE) but you cannot, at this time, include the end date.
Simple but like a charm:
$period = new DatePeriod(new DateTime('2015-01-01'), new DateInterval('P1D'), new DateTime('2015-01-15 +1 day'));
foreach ($period as $date) {
$dates[] = $date->format("Y-m-d");
}
//ONLY SHOWING
echo '<pre>';
var_dump($dates);
echo '</pre>';
exit();
function GetDays($sStartDate, $sEndDate){
// Firstly, format the provided dates.
// This function works best with YYYY-MM-DD
// but other date formats will work thanks
// to strtotime().
$sStartDate = gmdate("Y-m-d", strtotime($sStartDate));
$sEndDate = gmdate("Y-m-d", strtotime($sEndDate));
// Start the variable off with the start date
$aDays[] = $sStartDate;
// Set a 'temp' variable, sCurrentDate, with
// the start date - before beginning the loop
$sCurrentDate = $sStartDate;
// While the current date is less than the end date
while($sCurrentDate < $sEndDate){
// Add a day to the current date
$sCurrentDate = gmdate("Y-m-d", strtotime("+1 day", strtotime($sCurrentDate)));
// Add this new day to the aDays array
$aDays[] = $sCurrentDate;
}
// Once the loop has finished, return the
// array of days.
return $aDays;
}
use like
GetDays('2007-01-01', '2007-01-31');
You must add $end->modify('+1 day') to include last day of interval, for example the January will have a 31 days instead of 30 without using modify() method.
This version of code will include the last day of the interval:
$begin = new DateTime( '2018-08-01' );
$end = new DateTime( '2018-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>";
}
PHP doc link
This is short, sweet, and should work in PHP4+.
function getDatesFromRange($start, $end){
$dates = array($start);
while(end($dates) < $end){
$dates[] = date('Y-m-d', strtotime(end($dates).' +1 day'));
}
return $dates;
}
Short function. PHP 5.3 and up. Can take optional third param of any date format that strtotime can understand. Automatically reverses direction if end < start.
function getDatesFromRange($start, $end, $format='Y-m-d') {
return array_map(function($timestamp) use($format) {
return date($format, $timestamp);
},
range(strtotime($start) + ($start < $end ? 4000 : 8000), strtotime($end) + ($start < $end ? 8000 : 4000), 86400));
}
Test:
date_default_timezone_set('Europe/Berlin');
print_r(getDatesFromRange( '2016-7-28','2016-8-2' ));
print_r(getDatesFromRange( '2016-8-2','2016-7-28' ));
print_r(getDatesFromRange( '2016-10-28','2016-11-2' ));
print_r(getDatesFromRange( '2016-11-2','2016-10-28' ));
print_r(getDatesFromRange( '2016-4-2','2016-3-25' ));
print_r(getDatesFromRange( '2016-3-25','2016-4-2' ));
print_r(getDatesFromRange( '2016-8-2','2016-7-25' ));
print_r(getDatesFromRange( '2016-7-25','2016-8-2' ));
Output:
Array ( [0] => 2016-07-28 [1] => 2016-07-29 [2] => 2016-07-30 [3] => 2016-07-31 [4] => 2016-08-01 [5] => 2016-08-02 )
Array ( [0] => 2016-08-02 [1] => 2016-08-01 [2] => 2016-07-31 [3] => 2016-07-30 [4] => 2016-07-29 [5] => 2016-07-28 )
Array ( [0] => 2016-10-28 [1] => 2016-10-29 [2] => 2016-10-30 [3] => 2016-10-31 [4] => 2016-11-01 [5] => 2016-11-02 )
Array ( [0] => 2016-11-02 [1] => 2016-11-01 [2] => 2016-10-31 [3] => 2016-10-30 [4] => 2016-10-29 [5] => 2016-10-28 )
Array ( [0] => 2016-04-02 [1] => 2016-04-01 [2] => 2016-03-31 [3] => 2016-03-30 [4] => 2016-03-29 [5] => 2016-03-28 [6] => 2016-03-27 [7] => 2016-03-26 [8] => 2016-03-25 )
Array ( [0] => 2016-03-25 [1] => 2016-03-26 [2] => 2016-03-27 [3] => 2016-03-28 [4] => 2016-03-29 [5] => 2016-03-30 [6] => 2016-03-31 [7] => 2016-04-01 [8] => 2016-04-02 )
Array ( [0] => 2016-08-02 [1] => 2016-08-01 [2] => 2016-07-31 [3] => 2016-07-30 [4] => 2016-07-29 [5] => 2016-07-28 [6] => 2016-07-27 [7] => 2016-07-26 [8] => 2016-07-25 )
Array ( [0] => 2016-07-25 [1] => 2016-07-26 [2] => 2016-07-27 [3] => 2016-07-28 [4] => 2016-07-29 [5] => 2016-07-30 [6] => 2016-07-31 [7] => 2016-08-01 [8] => 2016-08-02 )
Here is a function, that will return date ranges in both directions and it works on PHP >=5.2.2 :
function createRange($start, $end, $format = 'Y-m-d') {
$start = new DateTime($start);
$end = new DateTime($end);
$invert = $start > $end;
$dates = array();
$dates[] = $start->format($format);
while ($start != $end) {
$start->modify(($invert ? '-' : '+') . '1 day');
$dates[] = $start->format($format);
}
return $dates;
}
Use example:
print_r(createRange('2010-10-01', '2010-10-05'));
/*Array
(
[0] => 2010-10-01
[1] => 2010-10-02
[2] => 2010-10-03
[3] => 2010-10-04
[4] => 2010-10-05
)*/
print_r(createRange('2010-10-05', '2010-10-01', 'j M Y'));
/*Array
(
[0] => 5 Oct 2010
[1] => 4 Oct 2010
[2] => 3 Oct 2010
[3] => 2 Oct 2010
[4] => 1 Oct 2010
)*/
demo
many ways of getting this done, but finally it all depends on PHP version you are using. Here is summary of all solutions:
get PHP version:
echo phpinfo();
PHP 5.3+
$period = new DatePeriod(
new DateTime('2010-10-01'),
new DateInterval('P1D'),
new DateTime('2010-10-05')
);
PHP 4+
/**
* creating between two date
* #param string since
* #param string until
* #param string step
* #param string date format
* #return array
* #author Ali OYGUR <alioygur#gmail.com>
*/
function dateRange($first, $last, $step = '+1 day', $format = 'd/m/Y' ) {
$dates = array();
$current = strtotime($first);
$last = strtotime($last);
while( $current <= $last ) {
$dates[] = date($format, $current);
$current = strtotime($step, $current);
}
return $dates;
}
PHP < 4
you should upgrade :)
// Specify the start date. This date can be any English textual format
$date_from = "2018-02-03";
$date_from = strtotime($date_from); // Convert date to a UNIX timestamp
// Specify the end date. This date can be any English textual format
$date_to = "2018-09-10";
$date_to = strtotime($date_to); // Convert date to a UNIX timestamp
// Loop from the start date to end date and output all dates inbetween
for ($i=$date_from; $i<=$date_to; $i+=86400) {
echo date("Y-m-d", $i).'<br />';
}
<?
print_r(getDatesFromRange( '2010-10-01', '2010-10-05' ));
function getDatesFromRange($startDate, $endDate)
{
$return = array($startDate);
$start = $startDate;
$i=1;
if (strtotime($startDate) < strtotime($endDate))
{
while (strtotime($start) < strtotime($endDate))
{
$start = date('Y-m-d', strtotime($startDate.'+'.$i.' days'));
$return[] = $start;
$i++;
}
}
return $return;
}
Solution for PHP 5.2 with DateTime objects. But startDate MUST be before endDate.
function createRange($startDate, $endDate) {
$tmpDate = new DateTime($startDate);
$tmpEndDate = new DateTime($endDate);
$outArray = array();
do {
$outArray[] = $tmpDate->format('Y-m-d');
} while ($tmpDate->modify('+1 day') <= $tmpEndDate);
return $outArray;
}
Using:
$dates = createRange('2010-10-01', '2010-10-05');
$dates contain:
Array( '2010-10-01', '2010-10-02', '2010-10-03', '2010-10-04', '2010-10-05' )
function createDateRangeArray($start, $end) {
// Modified by JJ Geewax
$range = array();
if (is_string($start) === true) $start = strtotime($start);
if (is_string($end) === true ) $end = strtotime($end);
if ($start > $end) return createDateRangeArray($end, $start);
do {
$range[] = date('Y-m-d', $start);
$start = strtotime("+ 1 day", $start);
}
while($start < $end);
return $range;
}
Source: http://boonedocks.net/mike/archives/137-Creating-a-Date-Range-Array-with-PHP.html
$report_starting_date=date('2014-09-16');
$report_ending_date=date('2014-09-26');
$report_starting_date1=date('Y-m-d',strtotime($report_starting_date.'-1 day'));
while (strtotime($report_starting_date1)<strtotime($report_ending_date))
{
$report_starting_date1=date('Y-m-d',strtotime($report_starting_date1.'+1 day'));
$dates[]=$report_starting_date1;
}
print_r($dates);
// dates ('2014-09-16', '2014-09-26')
//print result Array
(
[0] => 2014-09-16
[1] => 2014-09-17
[2] => 2014-09-18
[3] => 2014-09-19
[4] => 2014-09-20
[5] => 2014-09-21
[6] => 2014-09-22
[7] => 2014-09-23
[8] => 2014-09-24
[9] => 2014-09-25
[10] => 2014-09-26
)
Here's a way of doing this using Carbon https://github.com/briannesbitt/Carbon:
public function buildDateRangeArray($first, $last)
{
while ($first <= $last) {
$dates[] = $first->toDateString();
$first->addDay();
}
return $dates;
}
This, of course, can be tweaked to not use Carbon. The $first and $last parameters passed to the function are Carbon instances.
// will return dates array
function returnBetweenDates( $startDate, $endDate ){
$startStamp = strtotime( $startDate );
$endStamp = strtotime( $endDate );
if( $endStamp > $startStamp ){
while( $endStamp >= $startStamp ){
$dateArr[] = date( 'Y-m-d', $startStamp );
$startStamp = strtotime( ' +1 day ', $startStamp );
}
return $dateArr;
}else{
return $startDate;
}
}
returnBetweenDates( '2014-09-16', '2014-09-26' );
// print_r( returnBetweenDates( '2014-09-16', '2014-09-26' ) );
it will return array like below:
Array
(
[0] => 2014-09-16
[1] => 2014-09-17
[2] => 2014-09-18
[3] => 2014-09-19
[4] => 2014-09-20
[5] => 2014-09-21
[6] => 2014-09-22
[7] => 2014-09-23
[8] => 2014-09-24
[9] => 2014-09-25
[10] => 2014-09-26
)
I think it's the shortest answer
Edit the code as you like
for ($x=strtotime('2015-12-01');$x<=strtotime('2015-12-30');$x+=86400)
echo date('Y-m-d',$x);
I love a solid one-liner!
My php discovery of the day was that array_push() returns the new number of elements in the array.
I managed to check for the end date match, increment $x, and push new elements all within the two-part condition statement of an empty while loop.
function getDatesFromRange($a,$b,$x=0,$dates=[]){
while(end($dates)!=$b && $x=array_push($dates,date("Y-m-d",strtotime("$a +$x day"))));
return $dates;
}
var_export(getDatesFromRange('2010-10-01','2010-10-05'));
The most similar function to mine on this page is drolex's (which I didn't actually find until after I wrote mine, if you believe me). I did some speed tests across large and small date ranges and they seem to beat each other just as often -- so I'm calling them equal performers. Here are some other comparisons:
We both use date(), strtotime(), and two array functions.
Drolex uses just three variables, I use the same three plus $x.
Because loading the start date into the $date array is not necessary for my function, I can declare it in the function parameters and spare the line (likewise with $x).
**Just a couple of important notes:
1- Date strings MUST BE validated before being fed to the function.
2- The above function can only handle forward moving date ranges.
If you want backward moving date ranges, simply reverse the date order in the function call and add a minus after $x=. (Pretty slick, eh?)
function getDatesFromRange($a,$b,$x=0,$dates=[]){
while(end($dates)!=$b && $x=-array_push($dates,date("Y-m-d",strtotime("$a +$x day"))));
return $dates;
}
var_export(getDatesFromRange('2010-10-05','2010-10-01'));
One more extension/consideration...
Imagine you have a multi-cultural (or sloppy) user base, and your function MUST be able to receive start and end dates in different valid formats AND you need to be able to output the array in any of the valid formats? By minor adjustment, I've provided a solution for that.
By "valid" I mean YYYY-MM-DD, MM/DD/YYY, and DD-MM-YYYY, these are massively popular standards world-wide, if another format is necessary then usability would come down to strtotime's comprehension of it.
Here is the Demo.
Code:
function getDatesFromRange($a,$b,$format='Y-m-d',$dates=[],$x=0){
while(date($format,strtotime(end($dates)))!=date($format,strtotime($b)) && $x=array_push($dates,date($format,strtotime("$a +$x day"))));
return $dates;
}
$formats=array("Computer"=>'Y-m-d',"American"=>'m/d/Y','Non-American'=>'d-m-Y');
$start='15-02-2017'; // Non-American formatted start date
$end='2017-02-27'; // Computer formatted start date
foreach($formats as $label=>$format){
echo "<br>$label<br>";
var_export(getDatesFromRange($start,$end,$format));
echo "<br>";
}
Output
Computer
array ( 0 => '2017-02-15', 1 => '2017-02-16', 2 => '2017-02-17', 3 => '2017-02-18',
4 => '2017-02-19', 5 => '2017-02-20', 6 => '2017-02-21', 7 => '2017-02-22',
8 => '2017-02-23', 9 => '2017-02-24', 10 => '2017-02-25', 11 => '2017-02-26',
12 => '2017-02-27', )
American
array ( 0 => '02/15/2017', 1 => '02/16/2017', 2 => '02/17/2017', 3 => '02/18/2017',
4 => '02/19/2017', 5 => '02/20/2017', 6 => '02/21/2017', 7 => '02/22/2017',
8 => '02/23/2017', 9 => '02/24/2017', 10 => '02/25/2017', 11 => '02/26/2017',
12 => '02/27/2017', )
Non-American
array ( 0 => '15-02-2017', 1 => '16-02-2017', 2 => '17-02-2017', 3 => '18-02-2017',
4 => '19-02-2017', 5 => '20-02-2017', 6 => '21-02-2017', 7 => '22-02-2017',
8 => '23-02-2017', 9 => '24-02-2017', 10 => '25-02-2017', 11 => '26-02-2017',
12 => '27-02-2017', )
Now some people don't 100% trust strtotime() because of some buggy behaviors. I think I've read that it will foul up when trying to jump a month from a leap-day. However, unless someone can reproduce it to prove me wrong, strtotime() is never going to let you down when you are only incrementing by one day.
Here is the another solution. Please check this.
$first = '10/30/2017'; //starting date
$last= '10/11/2017'; //ending date
$first_time_arr=explode('/',$first);
$last_time_arr=explode('/',$last);
//create timestamp of starting date
$start_timestamp=mktime(0,0,0, $first_time_arr[0], $first_time_arr[1],$first_time_arr[2]);
//create timestamp of ending date
$end_timestamp=mktime(0,0,0, $last_time_arr[0], $last_time_arr[1],$last_time_arr[2]);
$date_arr=array();
for($i=$start_timestamp;$i<=$end_timestamp;$i=$i+86400){
$date_arr[]=date("Y-m-d",$i); //this will save all dates in array
}
public static function countDays($date1,$date2)
{
$date1 = strtotime($date1); // or your date as well
$date2 = strtotime($date2);
$datediff = $date1 - $date2;
return floor($datediff/(60*60*24));
}
public static function dateRange($date1,$date2)
{
$count = static::countDays($date1,$date2) + 1;
$dates = array();
for($i=0;$i<$count;$i++)
{
$dates[] = date("Y-m-d",strtotime($date2.'+'.$i.' days'));
}
return $dates;
}
function datesbetween ($date1,$date2)
{
$dates= array();
for ($i = $date1
; $i<= $date1
; $i=date_add($i, date_interval_create_from_date_string('1 days')) )
{
$dates[] = clone $i;
}
return $dates;
}
To make Mostafa's answer complete, this is definietly the simplest and most efficient way to do it:
function getDatesFromRange($start_date, $end_date, $date_format = 'Y-m-d')
{
$dates_array = array();
for ($x = strtotime($start_date); $x <= strtotime($end_date); $x += 86400) {
array_push($dates_array, date($date_format, $x));
}
return $dates_array;
}
// see the dates in the array
print_r( getDatesFromRange('2017-02-09', '2017-02-19') );
You can even change the default output date format if you add a third parameter when you call the function, otherwise it will use the default format that's been set as 'Y-m-d'.
I hope it helps :)
function getWeekdayDatesFrom($format, $start_date_epoch, $end_date_epoch, $range) {
$dates_arr = array();
if( ! $range) {
$range = round(abs($start_date_epoch-$end_date_epoch)/86400) + 1;
} else {
$range = $range + 1; //end date inclusive
}
$current_date_epoch = $start_date_epoch;
for($i = 1; $i <= $range; $i+1) {
$d = date('N', $current_date_epoch);
if($d <= 5) { // not sat or sun
$dates_arr[] = "'".date($format, $current_date_epoch)."'";
}
$next_day_epoch = strtotime('+'.$i.'day', $start_date_epoch);
$i++;
$current_date_epoch = $next_day_epoch;
}
return $dates_arr;
}
$arr = range(strtotime("2013-12-01"),strtotime("2013-12-31"), "86400");
array_walk_recursive($arr, function(&$element) { $element = date("Y-m-d", $element); });
print_r ($arr);
This question already has answers here:
I have 2 dates in PHP, how can I run a foreach loop to go through all of those days?
(13 answers)
Closed 4 years ago.
Expected Input:
getDatesFromRange( '2010-10-01', '2010-10-05' );
Expected Output:
Array( '2010-10-01', '2010-10-02', '2010-10-03', '2010-10-04', '2010-10-05' )
You could also take a look at the DatePeriod class:
$period = new DatePeriod(
new DateTime('2010-10-01'),
new DateInterval('P1D'),
new DateTime('2010-10-05')
);
Which should get you an array with DateTime objects.
To iterate
foreach ($period as $key => $value) {
//$value->format('Y-m-d')
}
function createDateRangeArray($strDateFrom,$strDateTo)
{
// takes two dates formatted as YYYY-MM-DD and creates an
// inclusive array of the dates between the from and to dates.
// could test validity of dates here but I'm already doing
// that in the main script
$aryRange = [];
$iDateFrom = mktime(1, 0, 0, substr($strDateFrom, 5, 2), substr($strDateFrom, 8, 2), substr($strDateFrom, 0, 4));
$iDateTo = mktime(1, 0, 0, substr($strDateTo, 5, 2), substr($strDateTo, 8, 2), substr($strDateTo, 0, 4));
if ($iDateTo >= $iDateFrom) {
array_push($aryRange, date('Y-m-d', $iDateFrom)); // first entry
while ($iDateFrom<$iDateTo) {
$iDateFrom += 86400; // add 24 hours
array_push($aryRange, date('Y-m-d', $iDateFrom));
}
}
return $aryRange;
}
source: http://boonedocks.net/mike/archives/137-Creating-a-Date-Range-Array-with-PHP.html
This is very very flexible.
/**
* Creating date collection between two dates
*
* <code>
* <?php
* # Example 1
* date_range("2014-01-01", "2014-01-20", "+1 day", "m/d/Y");
*
* # Example 2. you can use even time
* date_range("01:00:00", "23:00:00", "+1 hour", "H:i:s");
* </code>
*
* #author Ali OYGUR <alioygur#gmail.com>
* #param string since any date, time or datetime format
* #param string until any date, time or datetime format
* #param string step
* #param string date of output format
* #return array
*/
function date_range($first, $last, $step = '+1 day', $output_format = 'd/m/Y' ) {
$dates = array();
$current = strtotime($first);
$last = strtotime($last);
while( $current <= $last ) {
$dates[] = date($output_format, $current);
$current = strtotime($step, $current);
}
return $dates;
}
Note that the answer provided by ViNce does NOT include the end date for the period.
If you are using PHP 5.3+, your best bet is to use a function like this:
/**
* Generate an array of string dates between 2 dates
*
* #param string $start Start date
* #param string $end End date
* #param string $format Output format (Default: Y-m-d)
*
* #return array
*/
function getDatesFromRange($start, $end, $format = 'Y-m-d') {
$array = array();
$interval = new DateInterval('P1D');
$realEnd = new DateTime($end);
$realEnd->add($interval);
$period = new DatePeriod(new DateTime($start), $interval, $realEnd);
foreach($period as $date) {
$array[] = $date->format($format);
}
return $array;
}
Then, you would call the function as expected:
getDatesFromRange('2010-10-01', '2010-10-05');
Run demo
Note about DatePeriod class: You can use the 4th parameter of DatePeriod to exclude the start date (DatePeriod::EXCLUDE_START_DATE) but you cannot, at this time, include the end date.
Simple but like a charm:
$period = new DatePeriod(new DateTime('2015-01-01'), new DateInterval('P1D'), new DateTime('2015-01-15 +1 day'));
foreach ($period as $date) {
$dates[] = $date->format("Y-m-d");
}
//ONLY SHOWING
echo '<pre>';
var_dump($dates);
echo '</pre>';
exit();
function GetDays($sStartDate, $sEndDate){
// Firstly, format the provided dates.
// This function works best with YYYY-MM-DD
// but other date formats will work thanks
// to strtotime().
$sStartDate = gmdate("Y-m-d", strtotime($sStartDate));
$sEndDate = gmdate("Y-m-d", strtotime($sEndDate));
// Start the variable off with the start date
$aDays[] = $sStartDate;
// Set a 'temp' variable, sCurrentDate, with
// the start date - before beginning the loop
$sCurrentDate = $sStartDate;
// While the current date is less than the end date
while($sCurrentDate < $sEndDate){
// Add a day to the current date
$sCurrentDate = gmdate("Y-m-d", strtotime("+1 day", strtotime($sCurrentDate)));
// Add this new day to the aDays array
$aDays[] = $sCurrentDate;
}
// Once the loop has finished, return the
// array of days.
return $aDays;
}
use like
GetDays('2007-01-01', '2007-01-31');
You must add $end->modify('+1 day') to include last day of interval, for example the January will have a 31 days instead of 30 without using modify() method.
This version of code will include the last day of the interval:
$begin = new DateTime( '2018-08-01' );
$end = new DateTime( '2018-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>";
}
PHP doc link
This is short, sweet, and should work in PHP4+.
function getDatesFromRange($start, $end){
$dates = array($start);
while(end($dates) < $end){
$dates[] = date('Y-m-d', strtotime(end($dates).' +1 day'));
}
return $dates;
}
Short function. PHP 5.3 and up. Can take optional third param of any date format that strtotime can understand. Automatically reverses direction if end < start.
function getDatesFromRange($start, $end, $format='Y-m-d') {
return array_map(function($timestamp) use($format) {
return date($format, $timestamp);
},
range(strtotime($start) + ($start < $end ? 4000 : 8000), strtotime($end) + ($start < $end ? 8000 : 4000), 86400));
}
Test:
date_default_timezone_set('Europe/Berlin');
print_r(getDatesFromRange( '2016-7-28','2016-8-2' ));
print_r(getDatesFromRange( '2016-8-2','2016-7-28' ));
print_r(getDatesFromRange( '2016-10-28','2016-11-2' ));
print_r(getDatesFromRange( '2016-11-2','2016-10-28' ));
print_r(getDatesFromRange( '2016-4-2','2016-3-25' ));
print_r(getDatesFromRange( '2016-3-25','2016-4-2' ));
print_r(getDatesFromRange( '2016-8-2','2016-7-25' ));
print_r(getDatesFromRange( '2016-7-25','2016-8-2' ));
Output:
Array ( [0] => 2016-07-28 [1] => 2016-07-29 [2] => 2016-07-30 [3] => 2016-07-31 [4] => 2016-08-01 [5] => 2016-08-02 )
Array ( [0] => 2016-08-02 [1] => 2016-08-01 [2] => 2016-07-31 [3] => 2016-07-30 [4] => 2016-07-29 [5] => 2016-07-28 )
Array ( [0] => 2016-10-28 [1] => 2016-10-29 [2] => 2016-10-30 [3] => 2016-10-31 [4] => 2016-11-01 [5] => 2016-11-02 )
Array ( [0] => 2016-11-02 [1] => 2016-11-01 [2] => 2016-10-31 [3] => 2016-10-30 [4] => 2016-10-29 [5] => 2016-10-28 )
Array ( [0] => 2016-04-02 [1] => 2016-04-01 [2] => 2016-03-31 [3] => 2016-03-30 [4] => 2016-03-29 [5] => 2016-03-28 [6] => 2016-03-27 [7] => 2016-03-26 [8] => 2016-03-25 )
Array ( [0] => 2016-03-25 [1] => 2016-03-26 [2] => 2016-03-27 [3] => 2016-03-28 [4] => 2016-03-29 [5] => 2016-03-30 [6] => 2016-03-31 [7] => 2016-04-01 [8] => 2016-04-02 )
Array ( [0] => 2016-08-02 [1] => 2016-08-01 [2] => 2016-07-31 [3] => 2016-07-30 [4] => 2016-07-29 [5] => 2016-07-28 [6] => 2016-07-27 [7] => 2016-07-26 [8] => 2016-07-25 )
Array ( [0] => 2016-07-25 [1] => 2016-07-26 [2] => 2016-07-27 [3] => 2016-07-28 [4] => 2016-07-29 [5] => 2016-07-30 [6] => 2016-07-31 [7] => 2016-08-01 [8] => 2016-08-02 )
Here is a function, that will return date ranges in both directions and it works on PHP >=5.2.2 :
function createRange($start, $end, $format = 'Y-m-d') {
$start = new DateTime($start);
$end = new DateTime($end);
$invert = $start > $end;
$dates = array();
$dates[] = $start->format($format);
while ($start != $end) {
$start->modify(($invert ? '-' : '+') . '1 day');
$dates[] = $start->format($format);
}
return $dates;
}
Use example:
print_r(createRange('2010-10-01', '2010-10-05'));
/*Array
(
[0] => 2010-10-01
[1] => 2010-10-02
[2] => 2010-10-03
[3] => 2010-10-04
[4] => 2010-10-05
)*/
print_r(createRange('2010-10-05', '2010-10-01', 'j M Y'));
/*Array
(
[0] => 5 Oct 2010
[1] => 4 Oct 2010
[2] => 3 Oct 2010
[3] => 2 Oct 2010
[4] => 1 Oct 2010
)*/
demo
many ways of getting this done, but finally it all depends on PHP version you are using. Here is summary of all solutions:
get PHP version:
echo phpinfo();
PHP 5.3+
$period = new DatePeriod(
new DateTime('2010-10-01'),
new DateInterval('P1D'),
new DateTime('2010-10-05')
);
PHP 4+
/**
* creating between two date
* #param string since
* #param string until
* #param string step
* #param string date format
* #return array
* #author Ali OYGUR <alioygur#gmail.com>
*/
function dateRange($first, $last, $step = '+1 day', $format = 'd/m/Y' ) {
$dates = array();
$current = strtotime($first);
$last = strtotime($last);
while( $current <= $last ) {
$dates[] = date($format, $current);
$current = strtotime($step, $current);
}
return $dates;
}
PHP < 4
you should upgrade :)
// Specify the start date. This date can be any English textual format
$date_from = "2018-02-03";
$date_from = strtotime($date_from); // Convert date to a UNIX timestamp
// Specify the end date. This date can be any English textual format
$date_to = "2018-09-10";
$date_to = strtotime($date_to); // Convert date to a UNIX timestamp
// Loop from the start date to end date and output all dates inbetween
for ($i=$date_from; $i<=$date_to; $i+=86400) {
echo date("Y-m-d", $i).'<br />';
}
<?
print_r(getDatesFromRange( '2010-10-01', '2010-10-05' ));
function getDatesFromRange($startDate, $endDate)
{
$return = array($startDate);
$start = $startDate;
$i=1;
if (strtotime($startDate) < strtotime($endDate))
{
while (strtotime($start) < strtotime($endDate))
{
$start = date('Y-m-d', strtotime($startDate.'+'.$i.' days'));
$return[] = $start;
$i++;
}
}
return $return;
}
Solution for PHP 5.2 with DateTime objects. But startDate MUST be before endDate.
function createRange($startDate, $endDate) {
$tmpDate = new DateTime($startDate);
$tmpEndDate = new DateTime($endDate);
$outArray = array();
do {
$outArray[] = $tmpDate->format('Y-m-d');
} while ($tmpDate->modify('+1 day') <= $tmpEndDate);
return $outArray;
}
Using:
$dates = createRange('2010-10-01', '2010-10-05');
$dates contain:
Array( '2010-10-01', '2010-10-02', '2010-10-03', '2010-10-04', '2010-10-05' )
function createDateRangeArray($start, $end) {
// Modified by JJ Geewax
$range = array();
if (is_string($start) === true) $start = strtotime($start);
if (is_string($end) === true ) $end = strtotime($end);
if ($start > $end) return createDateRangeArray($end, $start);
do {
$range[] = date('Y-m-d', $start);
$start = strtotime("+ 1 day", $start);
}
while($start < $end);
return $range;
}
Source: http://boonedocks.net/mike/archives/137-Creating-a-Date-Range-Array-with-PHP.html
$report_starting_date=date('2014-09-16');
$report_ending_date=date('2014-09-26');
$report_starting_date1=date('Y-m-d',strtotime($report_starting_date.'-1 day'));
while (strtotime($report_starting_date1)<strtotime($report_ending_date))
{
$report_starting_date1=date('Y-m-d',strtotime($report_starting_date1.'+1 day'));
$dates[]=$report_starting_date1;
}
print_r($dates);
// dates ('2014-09-16', '2014-09-26')
//print result Array
(
[0] => 2014-09-16
[1] => 2014-09-17
[2] => 2014-09-18
[3] => 2014-09-19
[4] => 2014-09-20
[5] => 2014-09-21
[6] => 2014-09-22
[7] => 2014-09-23
[8] => 2014-09-24
[9] => 2014-09-25
[10] => 2014-09-26
)
Here's a way of doing this using Carbon https://github.com/briannesbitt/Carbon:
public function buildDateRangeArray($first, $last)
{
while ($first <= $last) {
$dates[] = $first->toDateString();
$first->addDay();
}
return $dates;
}
This, of course, can be tweaked to not use Carbon. The $first and $last parameters passed to the function are Carbon instances.
// will return dates array
function returnBetweenDates( $startDate, $endDate ){
$startStamp = strtotime( $startDate );
$endStamp = strtotime( $endDate );
if( $endStamp > $startStamp ){
while( $endStamp >= $startStamp ){
$dateArr[] = date( 'Y-m-d', $startStamp );
$startStamp = strtotime( ' +1 day ', $startStamp );
}
return $dateArr;
}else{
return $startDate;
}
}
returnBetweenDates( '2014-09-16', '2014-09-26' );
// print_r( returnBetweenDates( '2014-09-16', '2014-09-26' ) );
it will return array like below:
Array
(
[0] => 2014-09-16
[1] => 2014-09-17
[2] => 2014-09-18
[3] => 2014-09-19
[4] => 2014-09-20
[5] => 2014-09-21
[6] => 2014-09-22
[7] => 2014-09-23
[8] => 2014-09-24
[9] => 2014-09-25
[10] => 2014-09-26
)
I think it's the shortest answer
Edit the code as you like
for ($x=strtotime('2015-12-01');$x<=strtotime('2015-12-30');$x+=86400)
echo date('Y-m-d',$x);
I love a solid one-liner!
My php discovery of the day was that array_push() returns the new number of elements in the array.
I managed to check for the end date match, increment $x, and push new elements all within the two-part condition statement of an empty while loop.
function getDatesFromRange($a,$b,$x=0,$dates=[]){
while(end($dates)!=$b && $x=array_push($dates,date("Y-m-d",strtotime("$a +$x day"))));
return $dates;
}
var_export(getDatesFromRange('2010-10-01','2010-10-05'));
The most similar function to mine on this page is drolex's (which I didn't actually find until after I wrote mine, if you believe me). I did some speed tests across large and small date ranges and they seem to beat each other just as often -- so I'm calling them equal performers. Here are some other comparisons:
We both use date(), strtotime(), and two array functions.
Drolex uses just three variables, I use the same three plus $x.
Because loading the start date into the $date array is not necessary for my function, I can declare it in the function parameters and spare the line (likewise with $x).
**Just a couple of important notes:
1- Date strings MUST BE validated before being fed to the function.
2- The above function can only handle forward moving date ranges.
If you want backward moving date ranges, simply reverse the date order in the function call and add a minus after $x=. (Pretty slick, eh?)
function getDatesFromRange($a,$b,$x=0,$dates=[]){
while(end($dates)!=$b && $x=-array_push($dates,date("Y-m-d",strtotime("$a +$x day"))));
return $dates;
}
var_export(getDatesFromRange('2010-10-05','2010-10-01'));
One more extension/consideration...
Imagine you have a multi-cultural (or sloppy) user base, and your function MUST be able to receive start and end dates in different valid formats AND you need to be able to output the array in any of the valid formats? By minor adjustment, I've provided a solution for that.
By "valid" I mean YYYY-MM-DD, MM/DD/YYY, and DD-MM-YYYY, these are massively popular standards world-wide, if another format is necessary then usability would come down to strtotime's comprehension of it.
Here is the Demo.
Code:
function getDatesFromRange($a,$b,$format='Y-m-d',$dates=[],$x=0){
while(date($format,strtotime(end($dates)))!=date($format,strtotime($b)) && $x=array_push($dates,date($format,strtotime("$a +$x day"))));
return $dates;
}
$formats=array("Computer"=>'Y-m-d',"American"=>'m/d/Y','Non-American'=>'d-m-Y');
$start='15-02-2017'; // Non-American formatted start date
$end='2017-02-27'; // Computer formatted start date
foreach($formats as $label=>$format){
echo "<br>$label<br>";
var_export(getDatesFromRange($start,$end,$format));
echo "<br>";
}
Output
Computer
array ( 0 => '2017-02-15', 1 => '2017-02-16', 2 => '2017-02-17', 3 => '2017-02-18',
4 => '2017-02-19', 5 => '2017-02-20', 6 => '2017-02-21', 7 => '2017-02-22',
8 => '2017-02-23', 9 => '2017-02-24', 10 => '2017-02-25', 11 => '2017-02-26',
12 => '2017-02-27', )
American
array ( 0 => '02/15/2017', 1 => '02/16/2017', 2 => '02/17/2017', 3 => '02/18/2017',
4 => '02/19/2017', 5 => '02/20/2017', 6 => '02/21/2017', 7 => '02/22/2017',
8 => '02/23/2017', 9 => '02/24/2017', 10 => '02/25/2017', 11 => '02/26/2017',
12 => '02/27/2017', )
Non-American
array ( 0 => '15-02-2017', 1 => '16-02-2017', 2 => '17-02-2017', 3 => '18-02-2017',
4 => '19-02-2017', 5 => '20-02-2017', 6 => '21-02-2017', 7 => '22-02-2017',
8 => '23-02-2017', 9 => '24-02-2017', 10 => '25-02-2017', 11 => '26-02-2017',
12 => '27-02-2017', )
Now some people don't 100% trust strtotime() because of some buggy behaviors. I think I've read that it will foul up when trying to jump a month from a leap-day. However, unless someone can reproduce it to prove me wrong, strtotime() is never going to let you down when you are only incrementing by one day.
Here is the another solution. Please check this.
$first = '10/30/2017'; //starting date
$last= '10/11/2017'; //ending date
$first_time_arr=explode('/',$first);
$last_time_arr=explode('/',$last);
//create timestamp of starting date
$start_timestamp=mktime(0,0,0, $first_time_arr[0], $first_time_arr[1],$first_time_arr[2]);
//create timestamp of ending date
$end_timestamp=mktime(0,0,0, $last_time_arr[0], $last_time_arr[1],$last_time_arr[2]);
$date_arr=array();
for($i=$start_timestamp;$i<=$end_timestamp;$i=$i+86400){
$date_arr[]=date("Y-m-d",$i); //this will save all dates in array
}
public static function countDays($date1,$date2)
{
$date1 = strtotime($date1); // or your date as well
$date2 = strtotime($date2);
$datediff = $date1 - $date2;
return floor($datediff/(60*60*24));
}
public static function dateRange($date1,$date2)
{
$count = static::countDays($date1,$date2) + 1;
$dates = array();
for($i=0;$i<$count;$i++)
{
$dates[] = date("Y-m-d",strtotime($date2.'+'.$i.' days'));
}
return $dates;
}
function datesbetween ($date1,$date2)
{
$dates= array();
for ($i = $date1
; $i<= $date1
; $i=date_add($i, date_interval_create_from_date_string('1 days')) )
{
$dates[] = clone $i;
}
return $dates;
}
To make Mostafa's answer complete, this is definietly the simplest and most efficient way to do it:
function getDatesFromRange($start_date, $end_date, $date_format = 'Y-m-d')
{
$dates_array = array();
for ($x = strtotime($start_date); $x <= strtotime($end_date); $x += 86400) {
array_push($dates_array, date($date_format, $x));
}
return $dates_array;
}
// see the dates in the array
print_r( getDatesFromRange('2017-02-09', '2017-02-19') );
You can even change the default output date format if you add a third parameter when you call the function, otherwise it will use the default format that's been set as 'Y-m-d'.
I hope it helps :)
function getWeekdayDatesFrom($format, $start_date_epoch, $end_date_epoch, $range) {
$dates_arr = array();
if( ! $range) {
$range = round(abs($start_date_epoch-$end_date_epoch)/86400) + 1;
} else {
$range = $range + 1; //end date inclusive
}
$current_date_epoch = $start_date_epoch;
for($i = 1; $i <= $range; $i+1) {
$d = date('N', $current_date_epoch);
if($d <= 5) { // not sat or sun
$dates_arr[] = "'".date($format, $current_date_epoch)."'";
}
$next_day_epoch = strtotime('+'.$i.'day', $start_date_epoch);
$i++;
$current_date_epoch = $next_day_epoch;
}
return $dates_arr;
}
$arr = range(strtotime("2013-12-01"),strtotime("2013-12-31"), "86400");
array_walk_recursive($arr, function(&$element) { $element = date("Y-m-d", $element); });
print_r ($arr);
I would like to know if its possible to split a given date range into 2 separate dates ranges if some certain criteria is met?
I am building a holiday booking system and need to split dates if holiday is booked off over 2 years. Example:
start date: 22-12-2013
end date: 04-01-2014
With the dates above i would like to split them into 2 lots of date ranges, so i would end up with something like this:
start date: 22-12-2013
end date: 31-12-2013
and then:
start date: 01-01-2014
end date: 04-01-2014
Is this possible? If so can someone point me in the right direction in what i need to search for in google?
if you want to split more months you can use this function:
function getMonthRanges($start, $end) {
$timeStart = strtotime($start);
$timeEnd = strtotime($end);
$out = [];
$milestones[] = $timeStart;
$timeEndMonth = strtotime('first day of next month midnight', $timeStart);
while ($timeEndMonth < $timeEnd) {
$milestones[] = $timeEndMonth;
$timeEndMonth = strtotime('+1 month', $timeEndMonth);
}
$milestones[] = $timeEnd;
$count = count($milestones);
for ($i = 1; $i < $count; $i++) {
$out[] = [
'start' => $milestones[$i - 1], // Here you can apply your formatting (like "date('Y-m-d H:i:s', $milestones[$i-1])") if you don't won't want just timestamp
'end' => $milestones[$i] - 1
];
}
return $out;
}
Using:
$result = getMonthRanges('15-11-2014', '19-11-2014');
Result:
Array
(
[0] => Array
(
[start] => 1418594400
[end] => 1420063199
)
[1] => Array
(
[start] => 1420063200
[end] => 1422741599
)
[2] => Array
(
[start] => 1422741600
[end] => 1425160799
)
[3] => Array
(
[start] => 1425160800
[end] => 1426715999
)
)
Human readable result:
array_walk_recursive($result, 'applyFormat');
function applyFormat(&$item)
{
$item = date('Y-m-d H:i:s', $item);
}
Array
(
[0] => Array
(
[start] => 2014-12-15 00:00:00
[end] => 2014-12-31 23:59:59
)
[1] => Array
(
[start] => 2015-01-01 00:00:00
[end] => 2015-01-31 23:59:59
)
[2] => Array
(
[start] => 2015-02-01 00:00:00
[end] => 2015-02-28 23:59:59
)
[3] => Array
(
[start] => 2015-03-01 00:00:00
[end] => 2015-03-18 23:59:59
)
)
That's a really basic approach, but I think it could be interesting investigating on something like this:
$date1 = '22-12-2013';
$date2 = "04-01-2014";
function split_date($d1, $d2)
{
$start_year = substr($d1, -4);
$end_year = substr($d2, -4);
if($end_year > $start_year)
{
$d1 .= ' ['.date('d-m-Y',strtotime("last day of December".$start_year)).'] <br />';
$d2 = '['.date('d-m-Y',strtotime("first day of January".$start_year)).'] ' . $d2;
}
return $d1 . $d2;
}
echo split_date($date1, $date2);
http://www.php.net/manual/en/datetime.formats.relative.php
Thanks to ilpaijin, this is what i came up with:
$date1 = '22-12-2013';
$date2 = "04-01-2014";
function split_date($d1, $d2)
{
$start_year = substr($d1, -4);
$end_year = substr($d2, -4);
if($end_year > $start_year)
{
$d1 .= ' ['.date('d-m-Y',strtotime("31-12-".$start_year)).'] <br />';
$d2 = '['.date('d-m-Y',strtotime("01-01-".$start_year."+1 years")).'] ' . $d2;
}
return $d1 . $d2;
}
echo split_date($date1, $date2);
In case of anyone want to split date range for any number of years, following is the implementation.
$date1 = '22-12-2013';
$date2 = '04-01-2017';
$dA = array();
function split_date($d1, $d2, &$dA)
{
$start_year = substr($d1, -4);
$end_year = substr($d2, -4);
if($end_year > $start_year)
{
$dA[] = $d1;
$dA[] = date('d-m-Y',strtotime("31-12-".$start_year));
if($end_year - $start_year == 1)
{
$dA[] = date('d-m-Y',strtotime("01-01-".$start_year."+1 years"));
$dA[] = $d2;
}else
{
split_date(date('d-m-Y',strtotime("01-01-".$start_year."+1 years")), $d2, $dA);
}
}else if($end_year == $start_year)
{
$dA[] = $d1;
$dA[] = $d2;
}
}
split_date($date1, $date2, $dA);
print_r($dA);
//Answer
Array
(
[0] => 22-12-2013
[1] => 31-12-2013
[2] => 01-01-2014
[3] => 31-12-2014
[4] => 01-01-2015
[5] => 31-12-2015
[6] => 01-01-2016
[7] => 31-12-2016
[8] => 01-01-2017
[9] => 04-01-2017
)
Very Simple way. You can split date range Supports for all types of date format.
function split_date($start_date,$end_date){
while($start_date < $end_date){
$end = date("Y-m-d", strtotime("Last day of December", strtotime($start_date)));
if($end_date<$end){
$end = $end_date;
}
$dates[] =array('start'=>$start_date,'end'=>$end);
$start_date =date("Y-m-d", strtotime("+1 day", strtotime($end)));
}
return $dates;
}
$dates = split_date('2011-01-02','2013-01-04');
print_r($dates);
OUPTPUT
Array
(
[0] => Array
(
[start] => 2011-01-02 //start date
[end] => 2011-12-31
)
[1] => Array
(
[start] => 2012-01-01
[end] => 2012-12-31
)
[2] => Array
(
[start] => 2013-01-01
[end] => 2013-01-04 //end date
)
)
Given these two YYYYMM strings:
$start = "201301";
$end = "201303";
I would like to derive an array like this:
array (
0 =>
array (
0 => '20130101',
1 => '20130131',
),
1 =>
array (
0 => '20130201',
1 => '20130228',
),
2 =>
array (
0 => '20130301',
1 => '20130331',
),
)
I've tried a few things with date() and mktime() but nothing decent so far.
What's a nice way to do this?
With DateTime:
$start = "201301";
$end = "201303";
$dateNiceStart = substr($start,0,4).'-'.substr($start,4).'-01';
$dateNiceEnd = substr($end,0,4).'-'.substr($end,4).'-';
// Days count in month
$endDays = date('t',strtotime($dateNiceEnd.'01'));
$dateNiceEnd .= $endDays;
$startObj = new DateTime($dateNiceStart);
$endObj = new DateTime($dateNiceEnd);
$temp = clone $startObj;
$arr = array();
// Adding first month
//Using first day and last day
$temp->modify( 'first day of this month' );
$start = $temp->format('Ymd');
$temp->modify( 'last day of this month' );
$end = $temp->format('Ymd');
$arr[] = array($start, $end);
do{
// for next month
$temp->modify( 'first day of next month' );
$start = $temp->format('Ymd');
$temp->modify( 'last day of this month' );
$end = $temp->format('Ymd');
$arr[] = array($start, $end);
// This line edited to work properly in different years, thanks to #Adidi
$interval = $endObj->diff($temp)->format('%y%m%d');
}
while ($interval!=0);
print_R($arr);
Main key is first/last day of next/this month usage.
http://www.php.net/manual/en/function.date.php
Which you need is format string "t":
t Number of days in the given month 28 through 31
Here is easy way to loop it..
$start = "201301";
$end = "201303";
$start_time = strtotime(implode('-',str_split($start,4)));
$end_time = strtotime(implode('-',str_split($end,4)));
$array = array();
if($start_time <= $end_time){
while($start_time <= $end_time){
$month = date('F', $start_time);
$array[] = array(
date('Ymd', strtotime("first day of {$month}", $start_time)),
date('Ymd', strtotime("last day of {$month}", $start_time)));
$start_time = strtotime("next month", $start_time);
}
}
Something like this?
for($i=1;$i<=12;$i++) {
$first = '2013'.($i<10 ? '0'.$i : $i).'01';
$last = date('Ymt', strtotime($first));
$myArray[] = array($first, $last);
}
Not tested.
You can iterate over the months like so:
function date_range($start, $end)
{
$start = strtotime("$start01");
$end = strtotime("$end01");
$res = array();
while ($start < $end) {
$next = strtotime("+1 month -1 day", $start);
$res[] = array(
date('Ymd', $start),
date('Ymd', $next),
);
$start = $next;
}
return $res;
}
Working solution:
$start = "201301";
$end = "201309";
function getDateTimeByString($str_date){
preg_match('/^([\d]{4})([\d]{2})$/',$str_date,$matches);
$dt = null;
if($matches){
$dt = new DateTime();
$dt->setDate($matches[1],$matches[2],1);
}
return $dt;
}
$start_dt = getDateTimeByString($start);
$end_dt = getDateTimeByString($end);
$output = array();
while($start_dt->getTimestamp() <= $end_dt->getTimestamp()){
$arr = array();
$arr[] = $start_dt->format('Ymd');
$start_dt->modify('last day of this month');
$arr[] = $start_dt->format('Ymd');
$output[] = $arr;
$start_dt->modify('first day of next month');
}
print_r($output);
prints:
Array
(
[0] => Array
(
[0] => 20130101
[1] => 20130131
)
[1] => Array
(
[0] => 20130201
[1] => 20130228
)
[2] => Array
(
[0] => 20130301
[1] => 20130331
)
[3] => Array
(
[0] => 20130401
[1] => 20130430
)
[4] => Array
(
[0] => 20130501
[1] => 20130531
)
[5] => Array
(
[0] => 20130601
[1] => 20130630
)
[6] => Array
(
[0] => 20130701
[1] => 20130731
)
[7] => Array
(
[0] => 20130801
[1] => 20130831
)
[8] => Array
(
[0] => 20130901
[1] => 20130930
)
)
You can try with these functions :
function get_date_range ($start, $end) {
$dates = array();
$start = strtotime($start .'01');
$end = strtotime($end .'01');
while ($start <= $end) {
$dates [] = array(date('Ym01', $start), date('Ymt', $start));
$start = strtotime(add_month(date('Y-m-01', $start), 1));
}
return $dates;
}
function add_month($date_value, $months, $format = 'm/d/Y') {
$date = new DateTime($date_value);
$start_day = $date->format('j');
$date->modify("+{$months} month");
$end_day = $date->format('j');
if ($start_day != $end_day)
$date->modify('last day of last month');
return $date->format($format);
}
$start = "201301";
$end = "201303";
$dates = get_date_range($start, $end);
print_r($dates);
Here the add_month function will help you to avoid problems with the date when adding one month to January 31st.
If you use strtotime it will go to March when adding 1 month to January 31st..
Output will be :
Array
(
[0] => Array
(
[0] => 2013-01-01
[1] => 2013-01-31
)
[1] => Array
(
[0] => 2013-02-01
[1] => 2013-02-28
)
[2] => Array
(
[0] => 2013-03-01
[1] => 2013-03-31
)
)
Hope this helps you :)
This question already has answers here:
I have 2 dates in PHP, how can I run a foreach loop to go through all of those days?
(13 answers)
Closed 4 years ago.
Expected Input:
getDatesFromRange( '2010-10-01', '2010-10-05' );
Expected Output:
Array( '2010-10-01', '2010-10-02', '2010-10-03', '2010-10-04', '2010-10-05' )
You could also take a look at the DatePeriod class:
$period = new DatePeriod(
new DateTime('2010-10-01'),
new DateInterval('P1D'),
new DateTime('2010-10-05')
);
Which should get you an array with DateTime objects.
To iterate
foreach ($period as $key => $value) {
//$value->format('Y-m-d')
}
function createDateRangeArray($strDateFrom,$strDateTo)
{
// takes two dates formatted as YYYY-MM-DD and creates an
// inclusive array of the dates between the from and to dates.
// could test validity of dates here but I'm already doing
// that in the main script
$aryRange = [];
$iDateFrom = mktime(1, 0, 0, substr($strDateFrom, 5, 2), substr($strDateFrom, 8, 2), substr($strDateFrom, 0, 4));
$iDateTo = mktime(1, 0, 0, substr($strDateTo, 5, 2), substr($strDateTo, 8, 2), substr($strDateTo, 0, 4));
if ($iDateTo >= $iDateFrom) {
array_push($aryRange, date('Y-m-d', $iDateFrom)); // first entry
while ($iDateFrom<$iDateTo) {
$iDateFrom += 86400; // add 24 hours
array_push($aryRange, date('Y-m-d', $iDateFrom));
}
}
return $aryRange;
}
source: http://boonedocks.net/mike/archives/137-Creating-a-Date-Range-Array-with-PHP.html
This is very very flexible.
/**
* Creating date collection between two dates
*
* <code>
* <?php
* # Example 1
* date_range("2014-01-01", "2014-01-20", "+1 day", "m/d/Y");
*
* # Example 2. you can use even time
* date_range("01:00:00", "23:00:00", "+1 hour", "H:i:s");
* </code>
*
* #author Ali OYGUR <alioygur#gmail.com>
* #param string since any date, time or datetime format
* #param string until any date, time or datetime format
* #param string step
* #param string date of output format
* #return array
*/
function date_range($first, $last, $step = '+1 day', $output_format = 'd/m/Y' ) {
$dates = array();
$current = strtotime($first);
$last = strtotime($last);
while( $current <= $last ) {
$dates[] = date($output_format, $current);
$current = strtotime($step, $current);
}
return $dates;
}
Note that the answer provided by ViNce does NOT include the end date for the period.
If you are using PHP 5.3+, your best bet is to use a function like this:
/**
* Generate an array of string dates between 2 dates
*
* #param string $start Start date
* #param string $end End date
* #param string $format Output format (Default: Y-m-d)
*
* #return array
*/
function getDatesFromRange($start, $end, $format = 'Y-m-d') {
$array = array();
$interval = new DateInterval('P1D');
$realEnd = new DateTime($end);
$realEnd->add($interval);
$period = new DatePeriod(new DateTime($start), $interval, $realEnd);
foreach($period as $date) {
$array[] = $date->format($format);
}
return $array;
}
Then, you would call the function as expected:
getDatesFromRange('2010-10-01', '2010-10-05');
Run demo
Note about DatePeriod class: You can use the 4th parameter of DatePeriod to exclude the start date (DatePeriod::EXCLUDE_START_DATE) but you cannot, at this time, include the end date.
Simple but like a charm:
$period = new DatePeriod(new DateTime('2015-01-01'), new DateInterval('P1D'), new DateTime('2015-01-15 +1 day'));
foreach ($period as $date) {
$dates[] = $date->format("Y-m-d");
}
//ONLY SHOWING
echo '<pre>';
var_dump($dates);
echo '</pre>';
exit();
function GetDays($sStartDate, $sEndDate){
// Firstly, format the provided dates.
// This function works best with YYYY-MM-DD
// but other date formats will work thanks
// to strtotime().
$sStartDate = gmdate("Y-m-d", strtotime($sStartDate));
$sEndDate = gmdate("Y-m-d", strtotime($sEndDate));
// Start the variable off with the start date
$aDays[] = $sStartDate;
// Set a 'temp' variable, sCurrentDate, with
// the start date - before beginning the loop
$sCurrentDate = $sStartDate;
// While the current date is less than the end date
while($sCurrentDate < $sEndDate){
// Add a day to the current date
$sCurrentDate = gmdate("Y-m-d", strtotime("+1 day", strtotime($sCurrentDate)));
// Add this new day to the aDays array
$aDays[] = $sCurrentDate;
}
// Once the loop has finished, return the
// array of days.
return $aDays;
}
use like
GetDays('2007-01-01', '2007-01-31');
You must add $end->modify('+1 day') to include last day of interval, for example the January will have a 31 days instead of 30 without using modify() method.
This version of code will include the last day of the interval:
$begin = new DateTime( '2018-08-01' );
$end = new DateTime( '2018-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>";
}
PHP doc link
This is short, sweet, and should work in PHP4+.
function getDatesFromRange($start, $end){
$dates = array($start);
while(end($dates) < $end){
$dates[] = date('Y-m-d', strtotime(end($dates).' +1 day'));
}
return $dates;
}
Short function. PHP 5.3 and up. Can take optional third param of any date format that strtotime can understand. Automatically reverses direction if end < start.
function getDatesFromRange($start, $end, $format='Y-m-d') {
return array_map(function($timestamp) use($format) {
return date($format, $timestamp);
},
range(strtotime($start) + ($start < $end ? 4000 : 8000), strtotime($end) + ($start < $end ? 8000 : 4000), 86400));
}
Test:
date_default_timezone_set('Europe/Berlin');
print_r(getDatesFromRange( '2016-7-28','2016-8-2' ));
print_r(getDatesFromRange( '2016-8-2','2016-7-28' ));
print_r(getDatesFromRange( '2016-10-28','2016-11-2' ));
print_r(getDatesFromRange( '2016-11-2','2016-10-28' ));
print_r(getDatesFromRange( '2016-4-2','2016-3-25' ));
print_r(getDatesFromRange( '2016-3-25','2016-4-2' ));
print_r(getDatesFromRange( '2016-8-2','2016-7-25' ));
print_r(getDatesFromRange( '2016-7-25','2016-8-2' ));
Output:
Array ( [0] => 2016-07-28 [1] => 2016-07-29 [2] => 2016-07-30 [3] => 2016-07-31 [4] => 2016-08-01 [5] => 2016-08-02 )
Array ( [0] => 2016-08-02 [1] => 2016-08-01 [2] => 2016-07-31 [3] => 2016-07-30 [4] => 2016-07-29 [5] => 2016-07-28 )
Array ( [0] => 2016-10-28 [1] => 2016-10-29 [2] => 2016-10-30 [3] => 2016-10-31 [4] => 2016-11-01 [5] => 2016-11-02 )
Array ( [0] => 2016-11-02 [1] => 2016-11-01 [2] => 2016-10-31 [3] => 2016-10-30 [4] => 2016-10-29 [5] => 2016-10-28 )
Array ( [0] => 2016-04-02 [1] => 2016-04-01 [2] => 2016-03-31 [3] => 2016-03-30 [4] => 2016-03-29 [5] => 2016-03-28 [6] => 2016-03-27 [7] => 2016-03-26 [8] => 2016-03-25 )
Array ( [0] => 2016-03-25 [1] => 2016-03-26 [2] => 2016-03-27 [3] => 2016-03-28 [4] => 2016-03-29 [5] => 2016-03-30 [6] => 2016-03-31 [7] => 2016-04-01 [8] => 2016-04-02 )
Array ( [0] => 2016-08-02 [1] => 2016-08-01 [2] => 2016-07-31 [3] => 2016-07-30 [4] => 2016-07-29 [5] => 2016-07-28 [6] => 2016-07-27 [7] => 2016-07-26 [8] => 2016-07-25 )
Array ( [0] => 2016-07-25 [1] => 2016-07-26 [2] => 2016-07-27 [3] => 2016-07-28 [4] => 2016-07-29 [5] => 2016-07-30 [6] => 2016-07-31 [7] => 2016-08-01 [8] => 2016-08-02 )
Here is a function, that will return date ranges in both directions and it works on PHP >=5.2.2 :
function createRange($start, $end, $format = 'Y-m-d') {
$start = new DateTime($start);
$end = new DateTime($end);
$invert = $start > $end;
$dates = array();
$dates[] = $start->format($format);
while ($start != $end) {
$start->modify(($invert ? '-' : '+') . '1 day');
$dates[] = $start->format($format);
}
return $dates;
}
Use example:
print_r(createRange('2010-10-01', '2010-10-05'));
/*Array
(
[0] => 2010-10-01
[1] => 2010-10-02
[2] => 2010-10-03
[3] => 2010-10-04
[4] => 2010-10-05
)*/
print_r(createRange('2010-10-05', '2010-10-01', 'j M Y'));
/*Array
(
[0] => 5 Oct 2010
[1] => 4 Oct 2010
[2] => 3 Oct 2010
[3] => 2 Oct 2010
[4] => 1 Oct 2010
)*/
demo
many ways of getting this done, but finally it all depends on PHP version you are using. Here is summary of all solutions:
get PHP version:
echo phpinfo();
PHP 5.3+
$period = new DatePeriod(
new DateTime('2010-10-01'),
new DateInterval('P1D'),
new DateTime('2010-10-05')
);
PHP 4+
/**
* creating between two date
* #param string since
* #param string until
* #param string step
* #param string date format
* #return array
* #author Ali OYGUR <alioygur#gmail.com>
*/
function dateRange($first, $last, $step = '+1 day', $format = 'd/m/Y' ) {
$dates = array();
$current = strtotime($first);
$last = strtotime($last);
while( $current <= $last ) {
$dates[] = date($format, $current);
$current = strtotime($step, $current);
}
return $dates;
}
PHP < 4
you should upgrade :)
// Specify the start date. This date can be any English textual format
$date_from = "2018-02-03";
$date_from = strtotime($date_from); // Convert date to a UNIX timestamp
// Specify the end date. This date can be any English textual format
$date_to = "2018-09-10";
$date_to = strtotime($date_to); // Convert date to a UNIX timestamp
// Loop from the start date to end date and output all dates inbetween
for ($i=$date_from; $i<=$date_to; $i+=86400) {
echo date("Y-m-d", $i).'<br />';
}
<?
print_r(getDatesFromRange( '2010-10-01', '2010-10-05' ));
function getDatesFromRange($startDate, $endDate)
{
$return = array($startDate);
$start = $startDate;
$i=1;
if (strtotime($startDate) < strtotime($endDate))
{
while (strtotime($start) < strtotime($endDate))
{
$start = date('Y-m-d', strtotime($startDate.'+'.$i.' days'));
$return[] = $start;
$i++;
}
}
return $return;
}
Solution for PHP 5.2 with DateTime objects. But startDate MUST be before endDate.
function createRange($startDate, $endDate) {
$tmpDate = new DateTime($startDate);
$tmpEndDate = new DateTime($endDate);
$outArray = array();
do {
$outArray[] = $tmpDate->format('Y-m-d');
} while ($tmpDate->modify('+1 day') <= $tmpEndDate);
return $outArray;
}
Using:
$dates = createRange('2010-10-01', '2010-10-05');
$dates contain:
Array( '2010-10-01', '2010-10-02', '2010-10-03', '2010-10-04', '2010-10-05' )
function createDateRangeArray($start, $end) {
// Modified by JJ Geewax
$range = array();
if (is_string($start) === true) $start = strtotime($start);
if (is_string($end) === true ) $end = strtotime($end);
if ($start > $end) return createDateRangeArray($end, $start);
do {
$range[] = date('Y-m-d', $start);
$start = strtotime("+ 1 day", $start);
}
while($start < $end);
return $range;
}
Source: http://boonedocks.net/mike/archives/137-Creating-a-Date-Range-Array-with-PHP.html
$report_starting_date=date('2014-09-16');
$report_ending_date=date('2014-09-26');
$report_starting_date1=date('Y-m-d',strtotime($report_starting_date.'-1 day'));
while (strtotime($report_starting_date1)<strtotime($report_ending_date))
{
$report_starting_date1=date('Y-m-d',strtotime($report_starting_date1.'+1 day'));
$dates[]=$report_starting_date1;
}
print_r($dates);
// dates ('2014-09-16', '2014-09-26')
//print result Array
(
[0] => 2014-09-16
[1] => 2014-09-17
[2] => 2014-09-18
[3] => 2014-09-19
[4] => 2014-09-20
[5] => 2014-09-21
[6] => 2014-09-22
[7] => 2014-09-23
[8] => 2014-09-24
[9] => 2014-09-25
[10] => 2014-09-26
)
Here's a way of doing this using Carbon https://github.com/briannesbitt/Carbon:
public function buildDateRangeArray($first, $last)
{
while ($first <= $last) {
$dates[] = $first->toDateString();
$first->addDay();
}
return $dates;
}
This, of course, can be tweaked to not use Carbon. The $first and $last parameters passed to the function are Carbon instances.
// will return dates array
function returnBetweenDates( $startDate, $endDate ){
$startStamp = strtotime( $startDate );
$endStamp = strtotime( $endDate );
if( $endStamp > $startStamp ){
while( $endStamp >= $startStamp ){
$dateArr[] = date( 'Y-m-d', $startStamp );
$startStamp = strtotime( ' +1 day ', $startStamp );
}
return $dateArr;
}else{
return $startDate;
}
}
returnBetweenDates( '2014-09-16', '2014-09-26' );
// print_r( returnBetweenDates( '2014-09-16', '2014-09-26' ) );
it will return array like below:
Array
(
[0] => 2014-09-16
[1] => 2014-09-17
[2] => 2014-09-18
[3] => 2014-09-19
[4] => 2014-09-20
[5] => 2014-09-21
[6] => 2014-09-22
[7] => 2014-09-23
[8] => 2014-09-24
[9] => 2014-09-25
[10] => 2014-09-26
)
I think it's the shortest answer
Edit the code as you like
for ($x=strtotime('2015-12-01');$x<=strtotime('2015-12-30');$x+=86400)
echo date('Y-m-d',$x);
I love a solid one-liner!
My php discovery of the day was that array_push() returns the new number of elements in the array.
I managed to check for the end date match, increment $x, and push new elements all within the two-part condition statement of an empty while loop.
function getDatesFromRange($a,$b,$x=0,$dates=[]){
while(end($dates)!=$b && $x=array_push($dates,date("Y-m-d",strtotime("$a +$x day"))));
return $dates;
}
var_export(getDatesFromRange('2010-10-01','2010-10-05'));
The most similar function to mine on this page is drolex's (which I didn't actually find until after I wrote mine, if you believe me). I did some speed tests across large and small date ranges and they seem to beat each other just as often -- so I'm calling them equal performers. Here are some other comparisons:
We both use date(), strtotime(), and two array functions.
Drolex uses just three variables, I use the same three plus $x.
Because loading the start date into the $date array is not necessary for my function, I can declare it in the function parameters and spare the line (likewise with $x).
**Just a couple of important notes:
1- Date strings MUST BE validated before being fed to the function.
2- The above function can only handle forward moving date ranges.
If you want backward moving date ranges, simply reverse the date order in the function call and add a minus after $x=. (Pretty slick, eh?)
function getDatesFromRange($a,$b,$x=0,$dates=[]){
while(end($dates)!=$b && $x=-array_push($dates,date("Y-m-d",strtotime("$a +$x day"))));
return $dates;
}
var_export(getDatesFromRange('2010-10-05','2010-10-01'));
One more extension/consideration...
Imagine you have a multi-cultural (or sloppy) user base, and your function MUST be able to receive start and end dates in different valid formats AND you need to be able to output the array in any of the valid formats? By minor adjustment, I've provided a solution for that.
By "valid" I mean YYYY-MM-DD, MM/DD/YYY, and DD-MM-YYYY, these are massively popular standards world-wide, if another format is necessary then usability would come down to strtotime's comprehension of it.
Here is the Demo.
Code:
function getDatesFromRange($a,$b,$format='Y-m-d',$dates=[],$x=0){
while(date($format,strtotime(end($dates)))!=date($format,strtotime($b)) && $x=array_push($dates,date($format,strtotime("$a +$x day"))));
return $dates;
}
$formats=array("Computer"=>'Y-m-d',"American"=>'m/d/Y','Non-American'=>'d-m-Y');
$start='15-02-2017'; // Non-American formatted start date
$end='2017-02-27'; // Computer formatted start date
foreach($formats as $label=>$format){
echo "<br>$label<br>";
var_export(getDatesFromRange($start,$end,$format));
echo "<br>";
}
Output
Computer
array ( 0 => '2017-02-15', 1 => '2017-02-16', 2 => '2017-02-17', 3 => '2017-02-18',
4 => '2017-02-19', 5 => '2017-02-20', 6 => '2017-02-21', 7 => '2017-02-22',
8 => '2017-02-23', 9 => '2017-02-24', 10 => '2017-02-25', 11 => '2017-02-26',
12 => '2017-02-27', )
American
array ( 0 => '02/15/2017', 1 => '02/16/2017', 2 => '02/17/2017', 3 => '02/18/2017',
4 => '02/19/2017', 5 => '02/20/2017', 6 => '02/21/2017', 7 => '02/22/2017',
8 => '02/23/2017', 9 => '02/24/2017', 10 => '02/25/2017', 11 => '02/26/2017',
12 => '02/27/2017', )
Non-American
array ( 0 => '15-02-2017', 1 => '16-02-2017', 2 => '17-02-2017', 3 => '18-02-2017',
4 => '19-02-2017', 5 => '20-02-2017', 6 => '21-02-2017', 7 => '22-02-2017',
8 => '23-02-2017', 9 => '24-02-2017', 10 => '25-02-2017', 11 => '26-02-2017',
12 => '27-02-2017', )
Now some people don't 100% trust strtotime() because of some buggy behaviors. I think I've read that it will foul up when trying to jump a month from a leap-day. However, unless someone can reproduce it to prove me wrong, strtotime() is never going to let you down when you are only incrementing by one day.
Here is the another solution. Please check this.
$first = '10/30/2017'; //starting date
$last= '10/11/2017'; //ending date
$first_time_arr=explode('/',$first);
$last_time_arr=explode('/',$last);
//create timestamp of starting date
$start_timestamp=mktime(0,0,0, $first_time_arr[0], $first_time_arr[1],$first_time_arr[2]);
//create timestamp of ending date
$end_timestamp=mktime(0,0,0, $last_time_arr[0], $last_time_arr[1],$last_time_arr[2]);
$date_arr=array();
for($i=$start_timestamp;$i<=$end_timestamp;$i=$i+86400){
$date_arr[]=date("Y-m-d",$i); //this will save all dates in array
}
public static function countDays($date1,$date2)
{
$date1 = strtotime($date1); // or your date as well
$date2 = strtotime($date2);
$datediff = $date1 - $date2;
return floor($datediff/(60*60*24));
}
public static function dateRange($date1,$date2)
{
$count = static::countDays($date1,$date2) + 1;
$dates = array();
for($i=0;$i<$count;$i++)
{
$dates[] = date("Y-m-d",strtotime($date2.'+'.$i.' days'));
}
return $dates;
}
function datesbetween ($date1,$date2)
{
$dates= array();
for ($i = $date1
; $i<= $date1
; $i=date_add($i, date_interval_create_from_date_string('1 days')) )
{
$dates[] = clone $i;
}
return $dates;
}
To make Mostafa's answer complete, this is definietly the simplest and most efficient way to do it:
function getDatesFromRange($start_date, $end_date, $date_format = 'Y-m-d')
{
$dates_array = array();
for ($x = strtotime($start_date); $x <= strtotime($end_date); $x += 86400) {
array_push($dates_array, date($date_format, $x));
}
return $dates_array;
}
// see the dates in the array
print_r( getDatesFromRange('2017-02-09', '2017-02-19') );
You can even change the default output date format if you add a third parameter when you call the function, otherwise it will use the default format that's been set as 'Y-m-d'.
I hope it helps :)
function getWeekdayDatesFrom($format, $start_date_epoch, $end_date_epoch, $range) {
$dates_arr = array();
if( ! $range) {
$range = round(abs($start_date_epoch-$end_date_epoch)/86400) + 1;
} else {
$range = $range + 1; //end date inclusive
}
$current_date_epoch = $start_date_epoch;
for($i = 1; $i <= $range; $i+1) {
$d = date('N', $current_date_epoch);
if($d <= 5) { // not sat or sun
$dates_arr[] = "'".date($format, $current_date_epoch)."'";
}
$next_day_epoch = strtotime('+'.$i.'day', $start_date_epoch);
$i++;
$current_date_epoch = $next_day_epoch;
}
return $dates_arr;
}
$arr = range(strtotime("2013-12-01"),strtotime("2013-12-31"), "86400");
array_walk_recursive($arr, function(&$element) { $element = date("Y-m-d", $element); });
print_r ($arr);