infotech infotech - 7 months ago 14
PHP Question

datetime: split a month 10-day periods

I send a earlier date and it returns me the periods between the earlier date and today cut by tens of days.


Example with 14/01/2016


I need the result to be exactly as below:


  • 11 Jan 2016 to 20 Jan 2016

  • 21 Jan 2016 to 31 Jan 2016

  • 01 Feb 2016 to 10 Feb 2016

  • 11 Feb 2016 to 20 Feb 2016

  • 21 Feb 2016 to 29 Feb 2016

  • 01 Mar 2016 to 10 Mar 2016

  • 11 Mar 2016 to 20 Mar 2016

  • 21 Mar 2016 to 31 Mar 2016

  • 01 Apr 2016 to 10 Apr 2016

  • 11 Apr 2016 to 20 Apr 2016



Here my code:

function date_interval($startTime = false){

if( ! $startTime){

return array();
} else {

if(date('d',$startTime) < 10){
$actual = mktime(0, 0, 0, date('m',$startTime), 1, date('Y',$startTime));
} elseif(date('d',$startTime) < 20){
$actual = mktime(0, 0, 0, date('m',$startTime), 10, date('Y',$startTime));
} else {
$actual = mktime(0, 0, 0, date('m',$startTime), 20, date('Y',$startTime));
}

if(date('d',time()) < 10) {
$target = mktime(0, 0, 0, date('m',time()), 10, date('Y',time()));
} elseif(date('d',time()) < 20) {
$target = mktime(0, 0, 0, date('m',time()), 20, date('Y',time()));
} else {
$target = mktime(0, 0, 0, date('m',time())+1, 1, date('Y',time()));
}


$current = $actual;
$last = $actual;

while($current < $target) {

if(date('d',$current) < 10){
$current = mktime(0, 0, 0, date('m',$current), 10, date('Y',$current));
} elseif(date('d',$current) < 20){
$current = mktime(0, 0, 0, date('m',$current), 20, date('Y',$current));
} else {
$current = mktime(0, 0, 0, date('m',$current)+1, 1, date('Y',$current));
}
$dateTime[date("Y-m-d", $last) .'~'. date("Y-m-d", $current)] = date('d M Y',$last) . ' - ' . date('d M Y',$current));
$last = $current;
}
}
return $dateTime;
}

Max Max
Answer

Datetime is the darling class from php that solves this type of problem nicely. Here you feed the startdate to the function as DATETIME object and the function throws back a stack of list tags.

In the loop startDay is beeing modyfied first by adding 10 days to make the jump and then by one to avoid the overlap. If you want a final line with the (less then ten days) time period from last startDay till today you can add something like:

$return .= '<li>From '.$startDay->format('d M Y').' to '.$today->format('d M Y').'</li>';

after the loop

function date_interval(DATETIME $startDay = NULL)
{
      if( NULL == $startDay){ 
        return array(); }

      $return = '';
      $today = new DATETIME('now');

      while(  $today->diff( $startDay )->format('%a%') > 10  )
      {
          $return .= '<li>From '.$startDay->format('d M Y').' to ';
          $startDay->modify('+10 days');
          $return .= $startDay->format('d M Y').'</li>
          ';
          $startDay->modify('+1 day');
      }
      return $return;
}

I altered the above more general solution to do exactly what you describe:

    <?php
function date_interval(DATETIME $startDay = NULL)
{
      if( NULL == $startDay){ 
        return array(); }

      $return = '';
      $today = new DATETIME('now');
      $startMonth = new DateTime('first day of '.$startDay->format('M Y') );
      $firstRun = TRUE;

      while(  $today > $startDay )
      {
          $return .= '<li>From '.$startDay->format('d M Y').' to ';
          if( $firstRun == TRUE ){
            if( (int)$startDay->format('d') > 10 )
              $startMonth->modify('+10 days');
            if( (int)$startDay->format('d') > 20 )  
              $startMonth->modify('+10 days');
            $startDay = $startMonth;

            $firstRun = FALSE;
          }
          $lastOfMonth = new DateTime('last day of '.$startDay->format('M Y') );
          if( $lastOfMonth->diff( $startDay )->format('%a%') > 10 )
            $startDay->modify('+9 days');
          else
            $startDay = $lastOfMonth;

          $return .= $startDay->format('d M Y').'</li>
          ';
          $startDay->modify('+1 day');
      }
      return $return;
}

echo date_interval( date_create_from_format('Y-m-d','2016-01-21') )."\n";

?>