Reputation: 11
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?
Upvotes: 0
Views: 190
Reputation: 3823
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.
Upvotes: 2
Reputation: 6335
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 :)
Upvotes: 0
Reputation: 5253
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
)
)
Upvotes: 0
Reputation: 4686
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);
}
}
Upvotes: 1
Reputation: 256
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
Upvotes: 1
Reputation: 173562
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;
}
Upvotes: 0
Reputation: 1306
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.
Upvotes: 0