如何将两个日期缩小到一个日期范围?

时间:2015-05-04 15:54:08

标签: php date time range

我需要显示如下日期范围:

  • 2015年5月5日至7日
  • 2015年4月29日至5月5日
  • 2015年12月30日 - 2016年1月1日

我提供了作为PHP日期对象的开始日期和结束日期。有没有办法可以解析那些用PHP输出的东西?

编辑:我认为你们误解了我的目标。

我有一个WordPress事件插件,可以输出开始日期和结束日期。如果活动的开始日期为2015年5月4日,结束日期为2015年5月7日,我需要显示:

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

我不需要在给定日期之间显示每个日期;这对我来说很容易理解。

编辑2:好的,只是为了确保我完全清楚:

我使用Tri.be Events插件允许用户创建活动日历。在这个WordPress网站的首页上,我需要显示即将发生的事件列表。每个事件应该像这样输出:

此事件应按如下方式输出:

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

我遇到问题的是<time>元素。下面的答案似乎表明我想以这种格式输出时间:

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

这是不正确的。如果那样的情况下,我可以轻松地自己输出这个。正确的格式是:

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

因此,问题是:&#34;如何将两个日期缩小到一个日期范围?&#34;

3 个答案:

答案 0 :(得分:1)

编辑2:

我已使用某种日期格式更新了该功能。

输出将是:

  

活动标题

     

时间:2010年2月28日 - 2010年3月2日

     

活动标题

     

时间:2010年3月4日 - 2010年3月5日

     

活动标题

     

时间:2010年12月31日 - 2011年1月5日

修改

我发现了这个(通过搜索) - &gt; Check for consecutive dates within a set and return as range

以下代码不是我的。这是来自@Darragh

的旧帖子
  

我对代码做了一些小修改以适应OP的问题。

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

旧答案(基于原始问题)。

$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

答案 1 :(得分:1)

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

修改

使用上面的PHP代码完成示例。

  

输出

     

2015年3月23日 - 2015年3月27日

    // 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

答案 2 :(得分:0)

这是最简单的解决方案:

$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