Edited at

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

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

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

Gistにも全く同じコードを公開しています。


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


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