0

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?

3
  • inner arrays must have first and last day of those months ? or all days ? Commented Apr 22, 2013 at 9:36
  • @Svetlio, inner arrays have two values, first day of month and last day of month. Commented Apr 22, 2013 at 9:38
  • I don't know what you are trying to accomplish, but setting up an array with first and last day of each month looks strange to me. Maybe the PHP DateTime classes are something for you; especially DatePeriod and DateInterval. Commented Apr 22, 2013 at 10:07

7 Answers 7

2

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.

Sign up to request clarification or add additional context in comments.

5 Comments

-1 This solution is not good if it's different year - try to set $end = "201403";
you have syntax error - there: $interval = $endObj->diff($temp)->format('%y%m%d');
what IDE are you using :) ?
Eclipse with PDT. Sometimes it help a lot, but sometimes make me crazy.
Eclipse is horrible for PHP - yee
1

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

Comments

1

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

Comments

0

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.

Comments

0

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

Comments

0

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
        )

)

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.