【PHP】開始日・終了日が設定されている項目を、期間をベースに切り分けて詰め直す

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">mysqlのDBテーブルからSELECTしてきた上のデータを、下みたいにPHPで詰め直したいんだけど、どうやったらできるのか全然設計できなくて最近マジで鬱。助けてPHPer <a href="https://t.co/IwwtOfeTVe">pic.twitter.com/IwwtOfeTVe</a></p>&mdash; HAL (@PET_HAL) <a href="https://twitter.com/PET_HAL/status/1093117885151469568?ref_src=twsrc%5Etfw">2019年2月6日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

…とツイートを投稿したところ、

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">想定が間違っているかもですが、日付をtimestamp型にしてそれをindexにしてデータをを格納し、A,Bをindex単位でマージしたものを任意の期間で切り分ければ何とかなりそうな。</p>&mdash; まとっち (@raja_narinari) <a href="https://twitter.com/raja_narinari/status/1093128011983908864?ref_src=twsrc%5Etfw">2019年2月6日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

…とのアドバイスをいただき、とりあえず想定通りの結果が得られるコードが書けました。

※[Gist](https://gist.github.com/PET-HAL/a592971c1b43dd8c101a30e898425cc4)にも全く同じコードを公開しています。

```php:try.php
<?php

function convert_date_into_timestamp($date) {
    if (!$date) {
        return null;
    }
    return strtotime($date);
}

$list = array();
$tmp = array(
    'start_date' => '2019/01/21',
    'end_date' => '2019/02/28',
    'name' => 'A'
);
$list[] = $tmp;
$tmp = array(
    'start_date' => '2019/02/22',
    'end_date' => null,
    'name' => 'B'
);
$list[] = $tmp;

$start_date_list = array();
$end_date_list = array();
$tmp = array();

$list_count = count($list);
for ($i = 0; $i < $list_count; $i++) {
    $info = $list[$i];

    $start_date = convert_date_into_timestamp($info['start_date']);
    if ($start_date) {
        $start_date_list[] = $start_date;
    }

    $end_date = convert_date_into_timestamp($info['end_date']);
    if ($end_date) {
        $end_date_list[] = $end_date;
    }

    $arr = array(
        'start_date' => $start_date,
        'end_date' => $end_date,
        'name' => $info['name']
    );
    $tmp[] = $arr;
}

$start_date_list = array_unique($start_date_list);
$start_date_list = array_values($start_date_list);
sort($start_date_list);

$start_date_count = count($start_date_list);
for ($i = 0; $i < $start_date_count; $i++) {
    if ($i === 0) {
        continue;
    }
    $start_date_timestamp = $start_date_list[$i];
    $end_date_list[] = strtotime('-1 day', $start_date_timestamp);
}

$end_date_list = array_unique($end_date_list);
$end_date_list = array_values($end_date_list);
sort($end_date_list);

$end_date_timestamp = array_key_last($end_date_list);
if ($end_date_timestamp) {
    $start_date_list[] = strtotime('+1 day', $end_date_timestamp);
}

$start_date_list = array_unique($start_date_list);
$start_date_list = array_values($start_date_list);
sort($start_date_list);

$data = array();
$start_date_count = count($start_date_list);
for ($i = 0; $i < $start_date_count; $i++) {
    $start_date_timestamp = $start_date_list[$i];
    $end_date_timestamp = $end_date_list[$i];

    $name = '';
    for ($j = 0; $j < $list_count; $j++) {
        $info = $tmp[$j];

        $use_start_date_timestamp = $info['start_date'];
        $use_end_date_timestamp = $info['end_date'];
        if ($use_start_date_timestamp <= $start_date_timestamp
            && ($use_end_date_timestamp == null || ($end_date_timestamp != null && $use_end_date_timestamp >= $end_date_timestamp))) {
            if (!empty($name)) {
                $name .= '、';
            }
            $name .= $info['name'];
        }
    }

    // 2019/04/24 追加(バグ対応：終了日 < 本日 の場合に空行が出力されてしまう)
    if (empty($name)) {
        continue;
    }

    $arr = array(
        'start_date' => (string) date('Y-m-d', $start_date_timestamp),
        'end_date' => $end_date_timestamp != null ? (string) date('Y-m-d', $end_date_timestamp) : '',
        'name' => $name
    );
    $data[] = $arr;
}

var_dump(data);
```

期日が迫っていてブラッシュアップまで手が回せなかったのですが、改善の余地はまだまだありそうな気がしているので、時間がある時にリファクタリングしたいなあと思います。