生成(非) - 后续日期的人类可读列表

时间:2016-02-13 20:18:00

标签: php

当给出可以是后续日期的n个日期的列表时,它们只是简单的随机日期;什么是生成适当的人类可读字符串的最佳方法。

让我举个例子:

2016-02-13, 2016-02-14, 2016-02-15, 2016-02-16

应表示为:

feb 13th '16 - feb 16th '16

将日期转换为人类可读的对应物很容易;我对某种算法很感兴趣,可以将日期数组减少到尽可能短的解决方案。

当列表包含“漏洞”时,事情开始变得困难:

2016-02-13, 2016-02-14, 2016-02-15, 2016-03-02, 2016-03-03

feb 13th '16 - feb 15th '16 & mar 2nd '16 - mar 3rd '16

我已经打破了一段时间了;我没有进一步打破清单,订购它,让它独一无二,看看它们之间有多少天,并检查那里有多少元素。

但修复“漏洞”问题更难......我的解决方案不是防水......

有关如何解决此问题的任何想法?

2 个答案:

答案 0 :(得分:0)

匆忙写下,所以请仔细检查,尤其是夏令时。主要想法是我们需要获得间隔:

<?php
  date_default_timezone_set('UTC');

  $dates=explode(', ',
  '2015-02-13, 2015-02-14, 2015-02-15, 2015-02-16, 2016-02-13, 2016-02-14, 2016-02-15, 2016-03-02, 2016-03-03');

  $intervals = Array();
  $t0 = -1;
  $t = $t0;

  if(count($dates))
    foreach($dates as $d)
    {
      $t00 = strtotime("$d -1 day");
      if($t != $t00)
      {
        if($t0 != -1)
        {
          if($t == $t0)
            $intervals[]=date("M jS 'y",$t0);
          else
            $intervals[]=date("M jS 'y",$t0) . ' - ' . date("M jS 'y",$t);
        }
        $t = strtotime($d);
        $t0 = $t;
      }
      else
        $t = strtotime($d);
    }

  if ($t0 != $t)
    $intervals[]=date("M jS 'y",$t0) . ' - ' . date("M jS 'y",$t);

  echo join(" & ", $intervals);

结果:

Feb 13th '15 - Feb 16th '15 & Feb 13th '16 - Feb 15th '16 & Mar 2nd '16 - Mar 3rd '16

答案 1 :(得分:0)

在@ kay27的帮助下介绍搜索间隔的想法,这就是我现在创建间隔列表的方法。 假设这是一个雄辩模型中的方法,在$this->data中有一个数据列表。并使用Carbon生成漂亮的日期修饰符。

public function fd($format = 'Y-m-d')
{
    $dates = [];
    $intervals = [];

    foreach ($this->data as $d) {
        $dates[] = \Carbon::parse($d->datum);
    }
    // sort the dates..


    // init
    $i=0;
    $t=0;
    $peil = $dates[$i];
    $intervals[$t] = [$peil];

    // loop through the dates starting from 0+1, as we already
    // 'processed' the first entry.
    for ($i=1; $i < count($dates); $i++) {
        //  when not equal; then we will need to create a new inTerval,
        //  so we increase the index:
        if ($peil != $dates[$i]->copy()->subDay()) {
            $t++;
        }
        // adding the date to the appropriate interval.
        $intervals[$t][] = $dates[$i];
        // the reference date, as-in the last date added to the list.
        $peil = $dates[$i];
    }


    // do some formatting on the intervals

    return $intervals;
}