【问题标题】:How can I shrink two dates in to one date range?如何将两个日期缩小到一个日期范围内?
【发布时间】:2015-05-04 15:54:07
【问题描述】:

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

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

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

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

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

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

因此,问题是:“如何将两个日期缩小到一个日期范围内?”

【问题讨论】:

标签: php date time range


【解决方案1】:

编辑 2:

我已经用一些日期格式更新了函数。

输出将是:

活动标题

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

活动标题

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

活动标题

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

编辑:

我找到了这个(通过搜索)--> 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

【讨论】:

  • 很确定你误解了我正在寻找的东西,就像其他人显然有的一样。我已经更新了问题以更清楚。
  • 为什么要投反对票?我帮你。你投反对票。更清楚自己想要什么。
  • 但是,为什么要根据原始问题对答案投反对票?努力和时间肯定意味着什么?疯了。
  • 请查看我的更新。由于你的问题,我做了一些调整。 foreach ($ranges as $range) { $startDate = array_shift($range); $str = "

    活动标题

    "; $str .= "

    当:"; $str .= ""; $str .= sprintf('%s', $startDate->format('M j')); if (count($range)) { $endDate = array_pop($range); $str .= sprintf(' - %s', $endDate->format('j, Y')); $str .= "

    "; } 回声“

    $str

    ”; }
  • 这看起来很接近可以解决,尤其是您链接到的那个问题。如果我让它工作,我会标记为答案。谢谢。
【解决方案2】:
<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

【讨论】:

    【解决方案3】:

    这将是最简单的解决方案:

    $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
    

    【讨论】:

    • 我想你误解了我的目的;请查看更新后的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多