質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.61%

時間の差分を求めたい(PHP)

解決済

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 378

score 160

お世話になります。

文章だと難しいのですが、

例えば、2019年3月1日 10:00〜19:00の時間に対して

下記日時を埋めた時間配列を求めたいと思っています。
2019年3月1日 11:00〜12:00
2019年3月1日 15:15〜16:15
2019年3月1日 18:45〜19:45

出力としては

2019年3月1日 10:00〜11:00
2019年3月1日 12:00〜15:15
2019年3月1日 16:15〜18:45

を出したいと思っております。

何か良い方法は無いでしょうか。

分単位の配列にしないといけないでしょうか。

教えていただけますと幸いです。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • kei344

    2019/03/06 23:29

    ご自身で試されたコードを質問文に追記し、「何」が「どのように」わからないのか、コードのどの部分で詰まっているのかなどを具体的に追記されたほうが回答が望めると思います。https://teratail.com/help/question-tips

    キャンセル

回答 2

+3

年月日時刻の計算って、思った以上にややこしいですよね。

週カレンダーをベースとした、面談予約の仕組みを作成したことがあります。既に埋まった時間枠はグレーアウトして予約が入れられない、という感じでした。

似て非なるものかもしれませんが、たぶん、3月1日の例だけではなく、カレンダーも絡むのでは?、と思いました。

開始年月日時刻、終了年月日時刻をstrtotime(秒単位)で決め打ち(週カレンダーなら日曜10:00から土曜19:00とか)して、whileで1日ずつ回して、さらにその中でwhileで分単位(5分ごととか10分ごととか)で回し、さらにその中でif条件で配列を作成していく方法しか思い付きませんです。

$start = strtotime($start);
$end = strtotime($end);

while($start <= $end)
{
    $tstart = strtotime(date('Y-m-d', $start)." 10:00");
    $tend = strtotime(date('Y-m-d', $start)." 19:00");

    while($tstart <= $tend) {

        // ここに必要条件、除外条件を書いて、必要な配列を組成する。

        $tstart = $tstart + 300; // 5分(300秒)ずつ進める
    }

    $start = strtotime("+1 day", $start);
}


参考になれば幸いです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/03/07 11:38

    ありがとうございます、コメントが消えてしまっていました。
    1分ごとだとすごいメモリを消費してしまいそうですね、、
    試してみます

    キャンセル

checkベストアンサー

+2

「2019年3月1日 11:00〜12:00」を年月日、開始時間、終了時間に分け、配列に格納してみました。
11:00は1100という数値として扱っております。

function get_vacancy($start = 1000, $end = 1900, $booked = [])
{
    $result = [];

    foreach ($booked as $row)
    {
        if ($start < $row[0])
        {
            $a = $start;

            if ($row[0] < $end)
            {
                $b = $row[0];
            }
            else
            {
                $b = $end;
            }
            $result[] = [$a, $b];
        }

        if ($start < $row[1])
        {
            $start = $row[1];
        }
    }

    if ($start < $end)
    {
        $result[] = [$start, $end];
    }

    return $result;
}

// $taken: 埋まっている時間帯を配列に格納
$taken = [
    '2019-03-01' => [ [1100, 1200], [1515, 1615], [1845, 1945] ],
    '2019-03-02' => [ [1000, 1100], [1115, 1145], [1500, 1630] ],
    '2019-03-03' => [ ],
    '2019-03-04' => [ [900, 1100], [1115, 1145], [1500, 1930] ],
    '2019-03-05' => [ [900, 1100], [1045, 1145], [1500, 1630], [1615, 1715] ]
];

// $vacancies: 空き時間帯の配列
$vacancies = [];

foreach ($taken as $date => $times)
{
    $vacancy = get_vacancy(1000, 1900, $times);
    $vacancies[$date] = $vacancy;
}


// 以下、出力
if ($vacancies)
{
    echo "<ul>";
    foreach ($vacancies as $date => $times)
    {
        $date_f = date('Y年n月j日', strtotime($date));

        foreach ($times as $arr)
        {
            $time_f1 = substr(strval($arr[0]), -4, 2) . ":" . substr(strval($arr[0]), -2);
            $time_f2 = substr(strval($arr[1]), -4, 2) . ":" . substr(strval($arr[1]), -2);

            echo "<li>" . $date_f . $time_f1 . "〜" . $time_f2 . "</li>";
        }
    }
    echo "</ul>";
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/03/07 11:37

    ありがとうございます。コメントをしていたのですが、消えてしまっていました。。
    例えば、カレンダーから予定を取得してきたとして、
    $taken = [
    '2019-03-01' => [ [900, 1230], [1100, 1200],[1515, 1615], [1239, 1430], [1845, 1945] ],
    '2019-03-02' => [ [1000, 1100], [1115, 1145], [1500, 1630] ],
    '2019-03-03' => [ ],
    '2019-03-04' => [ [900, 1100], [1115, 1145], [1500, 1930] ]
    ];
    予定がだぶっている場合は、どのようにフィルターするのが良いでしょうか、、

    キャンセル

  • 2019/03/07 16:33

    予定がダブっていても対応できるようにコードを改良しましたのでご確認ください。
    ただし、$takenに配列を代入する際は日付、開始時間の昇順でソート済みであることを前提としてください。
    ループ処理の中で対応するより処理速度が速くなるはずです。

    キャンセル

  • 2019/03/07 17:57

    ありがとうございます、助かりました><

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.61%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る