首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从多个日期回显持续时间(例如。8月25日至27日,9月3日)

从多个日期回显持续时间(例如。8月25日至27日,9月3日)
EN

Stack Overflow用户
提问于 2021-08-25 16:00:52
回答 1查看 33关注 0票数 0

我正在处理的事情要么发生在一个单一的一天(前。5/20)或多天(例如。8/25、8/26、8/27、9/3)。

例如,考虑到在8/25、8/26、8/27和9/3期间举行的为期4天的活动,我想重复如下:

代码语言:javascript
复制
Aug 25-27, Sep 3

我想要密码:

  • 处理单日事件(前)。10月3日)
  • 组连续天数(前)。(1月25日至27日)
  • 用逗号隔开不连续的日子(例如。9月19日,22日)
  • 处理多个月的一系列日期(例如。2月28日至3月2日)
  • 必要时处理多个范围(例如。四月二日至四日(六月十日至十三日)
  • 避免多余的日期信息(例如。12月1日至3日,12月8日)

这很容易通过使用date()格式的单日事件来完成,但是在必要时可以使用多个日期智能地生成这样的格式吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-10-08 22:12:01

我创建了一个函数,它应该基于一个DateTime对象数组输出所需的字符串。我在函数中放置了一些内联注释,以指示在给定时间发生了什么。

代码语言:javascript
复制
function produceDateString(array $dates): string
{
    // sort the dates
    sort($dates);

    // create an array of arrays that contain ranges of consecutive days
    $ranges = [];
    $currentRange = [];
    foreach ($dates as $date) {
        if(empty($currentRange) || consecutive(end($currentRange), $date)) {
            $currentRange[] = $date;
        } else {
            $ranges[] = $currentRange;
            $currentRange = [$date];
        }
    }
    $ranges[] = $currentRange;

    // create the output string
    $output = '';
    $previous = null;
    foreach ($ranges as $range) {
        // add a comma between each range
        if (!empty($output)) {
            $output .= ', ';
        }

        // the long format should be used on the first occurrence of the loop
        // or when the month of first date in the range doesn't match 
        // the month of the last date in the previous range
        $format = $previous === null || end($previous)->format('m') !== reset($range)->format('m')
            ? 'M. j'
            : 'j';

        // the output differes when there are 1 or multiple dates in a range
        if (count($range) > 1) {
            // the output differs when the end and start are in the sane month
            $output .= sameMonth(reset($range), end($range))
                ? reset($range)->format($format).'-'.end($range)->format('j')
                : reset($range)->format('M. j').'-'.end($range)->format('M. j');
        } else {
            $output .= reset($range)->format($format);
        }

        $previous = $range;
    }

    return $output;
}

function consecutive(DateTime $t1, DateTime $t2): bool
{
    $t1->setTime(0, 0, 0, 0);
    $t2->setTime(0, 0, 0, 0);
    return(abs($t2->getTimestamp() - $t1->getTimestamp()) < 87000);
}

function sameMonth(DateTime $t1, DateTime $t2): bool
{
    return $t1->format('Y-m') === $t2->format('Y-m');
}

我制作了一个小3v4l来向您展示它是如何准确地工作的。不要犹豫,如果你可能有任何问题,这是如何运作。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68926248

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档