Skip to content
Advertisement

How can I divide a date range by number of months?

My dilemma is that if I request more than 6 months or so ( I do not know the approximate number ) from my webservices ( which gets called via JS ), I get nothing back. In other words, I have to limit it to 6 months.

So let’s consider this scenario:

$a = strtotime('June 3, 2011'); 
$b = strtotime('June 3, 2012');

I need to split this up by 6 months in order to make 2 distinct web servicerequests so that each call requests 6 months.

So with $a and $b, I need to split these up into as many date ranges as possible when taking the amount of months total divided by 6.

The first date range I need is from June 1, 2011 to November 31, 2011. The second date range I need is from December 1, 2011 to July 1, 2012.

The idea I had in mind was finding the number of months, then if it was greater than the limit variable 6, do a loop and increment the initial date by 6 months per loop.

Pseudo-code ( I actually initially wrote it in JS but figured it’d be easier to do in PHP because I wouldn’t have to deal with multiple asynchronous request behaviour ):

   var numMonths = monthDiff ( a, b ), ret = [], limit = 6, loopLimit = Math.ceil( numMonths / limit ), ranges = [];

    if ( numMonths > limit ) {

        for ( var i = 0; i<loopLimit; i++ ) {
            var start = new Date(b);
            var end = new Date ( b.setMonth( b.getMonth() + limit ) );
            ranges.push( start, end );
        }
    }

Does anyone know of a succinct way of doing this? Can anyone spot any programmatic flaws in this?

Advertisement

Answer

Try:

$a = strtotime("June 3, 2011 00:00:00Z"); 
$b = strtotime("June 3, 2012 00:00:00Z");
fetchAll($a,$b);

function fetchAll($a,$b) {
  $fetchLimit = "6 months";  // or, say, "180 days"; a string

  if ($b <= strtotime(gmdate("Y-m-d H:i:sZ",$a)." +".$fetchLimit)) {
    // it fits in one chunk
    fetchChunk($a,$b);
  }
  else {  // chunkify it!
    $lowerBound = $a;
    $upperBound = strtotime(gmdate("Y-m-d H:i:sZ",$a)." +".$fetchLimit);
    while ($upperBound < $b) { // fetch full chunks while there're some left
      fetchChunk($lowerBound,$upperBound);
      $lowerBound = $upperBound;
      $upperBound = strtotime(gmdate("Y-m-d H:i:sZ",$lowerBound)." +".$fetchLimit);
    }
    fetchChunk($lowerBound,$b); // get last (likely) partial chunk
  }

}

function fetchChunk($a,$b) {
  /* insert your function that actually grabs the partial data */
  //
  // for test, just display the chunk range:
  echo gmdate("Y-m-d H:i:sZ",$a)." to ".gmdate("Y-m-d H:i:sZ",$b)."<br>";
}

…where $fetchLimit in fetchAll() is any duration string parseable by strtotime(). You could then keep appending the output of each fetchChunk() to an initially blank variable which is later returned by fetchAll().

This example fetches two six-month “chunks”, as expected. Changing $b to one day later adds a third chunk containing only that extra day:

2011-06-03 00:00:00Z to 2011-12-03 00:00:00Z
2011-12-03 00:00:00Z to 2012-06-03 00:00:00Z
2012-06-03 00:00:00Z to 2012-06-04 00:00:00Z

Of course, PHP 5.3 has somewhat more elegant time functions like DateTime::diff, but the code above should work fine in PHP 5.2.x.

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement