How to get calendar weeks between two days correctly - php

Hi i need a code to get the week calendar numbers between two dates. I testes a little with some code from here but always get the wrong calendar numbers.
First Code :
$startDateUnix = strtotime('2014-09-21');
$endDateUnix = strtotime('2014-10-06');
$currentDateUnix = $startDateUnix;
$weekNumbers = array();
while ($currentDateUnix < $endDateUnix) {
$weekNumbers[] = date('W', $currentDateUnix);
$currentDateUnix = strtotime('+1 week', $currentDateUnix);
}
print_r($weekNumbers);
Second Code:
$start = '2014-09-22';
$end = '2014-10-06';
$dates = range(strtotime($start), strtotime($end),604800);
$weeks = array_map(function($v){return date('W', $v);}, $dates); // Requires PHP 5.3+
print_r($weeks);
and i get this out of both codes:
Array ( [0] => 38 [1] => 39 [2] => 40 )
But why is calendar week 41 not in ?

your second code returns the result like you expect:
$start = '2014-09-22';
$end = '2014-10-06';
$dates = range(strtotime($start), strtotime($end),604800);
$weeks = array_map(function($v){return date('W', $v);}, $dates); // Requires PHP 5.3+
print_r($weeks);
output:
Array
(
[0] => 39
[1] => 40
[2] => 41
)
the problem with your first code is that you start with 2014-09-21 (KW 38) and adding one week per loop. therefore the loop ends before the end date.
you can solve this by using the first code like this:
$startDateUnix = strtotime('2014-09-21');
$endDateUnix = strtotime('2014-10-06');
$currentDateUnix = $startDateUnix;
$weekNumbers = array();
while ($currentDateUnix <= $endDateUnix) {
$weekNumbers[] = date('W', $currentDateUnix);
$currentDateUnix = strtotime('+1 day', $currentDateUnix);
}
$weekNumbers = array_merge(array_unique($weekNumbers)); // array_merge to "reset" the keys
print_r($weekNumbers);
output:
Array
(
[0] => 38
[1] => 39
[2] => 40
[3] => 41
)

Related

Checking two dates between dates [duplicate]

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

Create PHP array of Hours, starting now and going backwards 24h [duplicate]

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

Distribute a month in weeks with start and end dates array

I'm making a function that would break current month into an array of weeks, each week with its starting and ending date. For example the current month is September, so this is what I expect my function to return:
$week_arr[1]['start'] = '1-09-2014';
$week_arr[1]['end'] = '7-09-2014';
$week_arr[2]['start'] = '8-09-2014';
$week_arr[2]['end'] = '14-09-2014';
/*
.
.
.
*/
$week_arr[5]['start'] = '29-09-2014';
$week_arr[5]['end'] = '30-09-2014';
I understand that only non-leap February will have 4 weeks.
This is what I have so far
$no_of_days_in_month = date("t");
$no_of_weeks = (ceil(intval($no_of_days_in_month)/7));
$week_inc = 0;
$curr_month_year = date("m-Y");
$week_arr = array();
for($i = 1; $i <= $no_of_weeks; $i++){
$week_arr[$i]['start'] = ($week_inc+1)."-".$curr_month_year;
$week_arr[$i]['end'] = ($week_inc+7)."-".$curr_month_year;
$week_inc += 7;
}
var_dump($week_arr);
It works almost correctly, except I want it to stop on the last day of the month in the last week.
Above code has a problem with the 5th index of the week. It results
$week_arr[5]['start'] = '29-09-2014'
$week_arr[5]['end'] = '35-09-2014'
How to fix that?
Thank you for your answers.
You could add a check to the start of your for loop to stop processing if the end date is greater than the number of days in the month:
if($week_inc + 7 > $no_of_days_in_month)
break;
Output
Or if you still want the partial week at the end, you could use a similar check to define what the last day should be:
for($i = 1; $i <= $no_of_weeks; $i++){
if($week_inc + 7 > $no_of_days_in_month)
$day = $no_of_days_in_month;
else
$day = $week_inc + 7;
$week_arr[$i]['start'] = ($week_inc+1)."-".$curr_month_year;
$week_arr[$i]['end'] = $day."-".$curr_month_year;
$week_inc += 7;
}
You'll then get a partial week at the end:
[5] => Array
(
[start] => 29-09-2014
[end] => 30-09-2014
)
Another option would be to use a DatePeriod class for this one too. Example:
$begin = new DateTime('first day of ' . date('Y-m-d'));
$end = new DateTime('last day of ' . date('Y-m-d'));
$interval = new DateInterval('P1W');
$daterange = new DatePeriod($begin, $interval, $end);
$dates = array();
foreach($daterange as $key => $date) {
$check = ($date->format('W') != $end->modify('last day of this month')->format('W')) ? '+6 days' : 'last day of this week';
$dates[$key+1] = array(
'start' => $date->format('Y-m-d'),
'end' => $date->modify($check)->format('Y-m-d'),
);
}
echo '<pre>';
print_r($dates);
Should yield this:
Array
(
[1] => Array
(
[start] => 2014-09-01
[end] => 2014-09-07
)
[2] => Array
(
[start] => 2014-09-08
[end] => 2014-09-14
)
[3] => Array
(
[start] => 2014-09-15
[end] => 2014-09-21
)
[4] => Array
(
[start] => 2014-09-22
[end] => 2014-09-28
)
[5] => Array
(
[start] => 2014-09-29
[end] => 2014-09-30
)
)

Create array of dates based on inputs

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 :)

PHP: Return all dates between two dates in an array [duplicate]

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

Categories