How can I shrink two dates in to one date range?

I need to display date ranges like the following:

  • May 5-7, 2015
  • April 29-May 5, 2015
  • December 30 2015-January 1, 2016

I'm provided a start date and an end date as PHP date objects. Is there a way I can parse those with PHP to output as needed?


EDIT: I think you guys are misunderstanding what I'm looking to do.

I've got a WordPress events plugin that outputs a start date and an end date. If an event has a start date of May 4, 2015, and an end date of May 7, 2015, I need to display this:

<h4>Event Title</h4>
<p>When: <time>May 4-7, 2015</time></p>

I don't need to display each date between the given dates; that's easy enough for me to figure out on my own.


EDIT 2: Alright, just to make sure I'm being completely clear:

I'm using the Tri.be Events plugin to allow a user to create a calendar of events. On the front page for this WordPress site, I need to display a list of upcoming events. Each event should be output like this:

This event should be output like this:

<article>
    <h4><a href="/path/to/event/">Systematic Implementation of Advance Care Planning in a Diverse City</a></h4>
    <p>
        <a href="/path/to/event/">
            Aging in America Conference - Chicago, IL<br />
            <time datetime="2015-03-23">March 23-27, 2015</time>
        </a>
    </p>
</article>

The bit I'm having trouble with is the <time> element. The answers below seem to indicate that I want to output the time in this format:

<time datetime="2015-03-23">March 23, 2015 - March 27, 2015</time>

This is incorrect. If that where the case, I could easily output this on my own. The correct format is:

<time datetime="2015-03-23">March 23-27, 2015</time>

Thus, the question is: "How can I shrink two dates in to one date range?"

Answers


EDIT 2:

I have updated the function with some date format.

Output will be:

Event title

When: Feb 28, 2010 - Mar 2, 2010

Event title

When: Mar 4, 2010 - Mar 5, 2010

Event title

When: Dec 31, 2010 - Jan 5, 2011

EDIT:

I found this (by searching) -- > Check for consecutive dates within a set and return as range

The code below isn't mine. It's an old post from @Darragh

I have made some minor changes to the code to fit the OP's question.

    // assuming a chronologically
    // ordered array of DateTime objects 

    $dates = array(         
          new DateTime('2010-02-28'), 
          new DateTime('2010-03-01'), 
          new DateTime('2010-03-02'), 
          new DateTime('2010-03-04'), 
          new DateTime('2010-03-05'), 
          new DateTime('2010-12-31'),
          new DateTime('2011-01-01'), 
          new DateTime('2011-01-02'), 
          new DateTime('2011-01-03'), 
          new DateTime('2011-01-04'), 
          new DateTime('2011-01-05'),
    );

    // process the array

    $lastDate = null;
    $ranges = array();
    $currentRange = array();

    foreach ($dates as $date) {    

        if (null === $lastDate) {
            $currentRange[] = $date;
        } else {

            // get the DateInterval object
            $interval = $date->diff($lastDate);

            // DateInterval has properties for 
            // days, weeks. months etc. You should 
            // implement some more robust conditions here to 
            // make sure all you're not getting false matches
            // for diffs like a month and a day, a year and 
            // a day and so on...

            if ($interval->days === 1) {
                // add this date to the current range
                $currentRange[] = $date;    
            } else {
                // store the old range and start anew
                $ranges[] = $currentRange;
                $currentRange = array($date);
            }
        }

        // end of iteration... 
        // this date is now the last date     
        $lastDate = $date;
    }

    // messy... 
    $ranges[] = $currentRange;

    // print dates

        foreach ($ranges as $range) {

    // there'll always be one array element, so 
    // shift that off and create a string from the date object 
    $startDate = array_shift($range);
    $str = "<h4>Event title</h4>";
    $str .= "<p>When: ";
    $str .= "<time>"; 
    $str .= sprintf('%s', $startDate->format('M j, Y'));
    // if there are still elements in $range
    // then this is a range. pop off the last 
    // element, do the same as above and concatenate
    if (count($range)) {
        $endDate = array_pop($range);
        $str .= sprintf(' - %s', $endDate->format('M j, Y'));
        $str .= "</time></p>";
    }

    echo "<p>$str</p>";
}

Old answer (based on original question).

$start_date = new DateTime( '2015-05-01' );
$end_date = new DateTime( '2015-05-04' );
$end_date = $end_date->modify( '+1 day' ); 

$interval = new DateInterval('P1D');
$daterange = new DatePeriod($start_date, $interval ,$end_date);

foreach($daterange as $date){
    echo $date->format("M d, Y") . "<br>";
}

// Output
// May 01, 2015
// May 02, 2015
// May 03, 2015
// May 04, 2015

<article>
    <h4><a href="/path/to/event/">Systematic Implementation of Advance Care Planning in a Diverse City</a></h4>
    <p>
        <a href="/path/to/event/">
            Aging in America Conference - Chicago, IL<br />
            <time datetime="2015-03-23/2015-03-27">March 23&ndash;27 2015</time>
        </a>
    </p>
</article>

Edit

Complete example with PHP-code above.

Output

Mar 23, 2015–Mar 27, 2015

    // assuming a chronologically
    // ordered array of DateTime objects 

    $dates = array(         
          new DateTime('2015-03-23'), 
          new DateTime('2015-03-24'), 
          new DateTime('2015-03-25'), 
          new DateTime('2015-03-26'), 
          new DateTime('2015-03-27')          
    );

    // process the array

    $lastDate = null;
    $ranges = array();
    $currentRange = array();

    foreach ($dates as $date) {    

        if (null === $lastDate) {
            $currentRange[] = $date;
        } else {

            // get the DateInterval object
            $interval = $date->diff($lastDate);

            // DateInterval has properties for 
            // days, weeks. months etc. You should 
            // implement some more robust conditions here to 
            // make sure all you're not getting false matches
            // for diffs like a month and a day, a year and 
            // a day and so on...

            if ($interval->days === 1) {
                // add this date to the current range
                $currentRange[] = $date;    
            } else {
                // store the old range and start anew
                $ranges[] = $currentRange;
                $currentRange = array($date);
            }
        }

        // end of iteration... 
        // this date is now the last date     
        $lastDate = $date;
    }

    // messy... 
    $ranges[] = $currentRange;

    // print dates

    foreach ($ranges as $range) {

    // there'll always be one array element, so 
    // shift that off and create a string from the date object 
    $startDate = array_shift($range);
    $str = "<h4>Event title</h4>";
    $str .= "<p>When: ";
    $str .= "<time>"; 
    $str .= sprintf('%s', $startDate->format('M j, Y'));
    // if there are still elements in $range
    // then this is a range. pop off the last 
    // element, do the same as above and concatenate
    if (count($range)) {
        $endDate = array_pop($range);
        $str .= sprintf(' - %s', $endDate->format('M j, Y'));
        $str .= "</time></p>";
    }

}

echo "<time datetime=".$startDate->format('M j, Y')."/".$endDate->format('M j, Y').">".$startDate->format('M j, Y')."&ndash;".$endDate->format('M j, Y')."</time>";

//OUTPUT
// Mar 23, 2015–Mar 27, 2015

This would be the simplest solution:

$dtStart = new DateTime('2015-05-05');
$dtEnd   = new DateTime('2015-05-07');

while ($dtStart <= $dtEnd) {
    echo $dtStart->format('Y-m-d') . "\n";
    $dtStart->modify('+1 day');
}

// Output:
// 2015-05-05
// 2015-05-06
// 2015-05-07

$dtStart = new DateTime('2015-12-30');
$dtEnd   = new DateTime('2016-01-01');

while ($dtStart <= $dtEnd) {
    echo $dtStart->format('Y-m-d') . "\n";
    $dtStart->modify('+1 day');
}

// Output:
// 2015-12-30
// 2015-12-31
// 2016-01-01

Need Your Help

Page shifts slightly when Bootstrap modal rendered

twitter-bootstrap modal-dialog

I've narrowed this down as much as possible in this fiddle. When you expand the right side as much as possible (to make Result area wide) and click on the Sign Up button, you will notice the page ...

Cannot resolve symbol 'container' - Android Studio

android android-studio

I just created a new projet, building some layouts, writing some code. Everything was fine except I got this error as shown in the picture below.