Skip to content
Advertisement

Get Possible Order Date Based On Multiple Conditions

I can’t wrap my head around this particular problem.

There is a bakery, and an office that accepts orders.

Bakery is open from Monday to Sunday, it’s only closed during public holidays.

Orders can be placed from Monday to Friday unless it’s a public holiday i.e. the office is open during working days.

We also need to distinguish if the user managed to order goods before or after a particular time, let’s say 12:00.

A few examples:

  1. It’s 22.7.2022 (Friday) at 10:00 – orders can be placed for the following days Saturday(23.7), Sunday(24.7), Monday(25.7), etc.
  2. It’s 22.7.2022 (Friday) at 13:00 – orders can be placed for the following days Tuesday(26.7), Wednesday(27.7), Thursday(28.7), etc.
  3. It’s 20.7.2022 (Wednesday) at 10:00 – orders can be placed for the following days Thursday(21.7), Friday(22.7), Saturday(23.7), etc.
  4. It’s 20.7.2022 (Wednesday) at 13:00 – orders can be placed for the following days Friday(22.7), Saturday(23.7), Sunday(24.7), etc.
  5. It’s 23.7.2022 (Saturday) and 24.7.2022 (Sunday) anytime – orders can be placed for the following days Tuesday(26.7), Wednesday(27.7), Thursday(28.7), etc.
  6. It’s 26.7.2022 (Monday) at 10:00 and 27.7(Tuesday) and 28.7(Wednesday) are public holidays – orders can be placed for the following days Thursday(28.7), Friday(29.7), Saturday(30.7), etc.
  7. It’s 26.7.2022 (Monday) at 13:00 and 27.7(Tuesday) and 28.7(Wednesday) are public holidays – orders can be placed for the following days Friday(29.7), Saturday(30.7), Sunday(31.7), etc.

This is what I’ve got so far, but the code isn’t working as expected.

function freeDays()
{
    return array(
        '01.01' // Den obnovy českého státu, Nový rok.
    , date('d.m', strtotime("-2 day", easter_date(date('Y')))) // Velký pátek
    , date('d.m', strtotime("+1 day", easter_date(date('Y')))) // Velikonoční pondělí
    ,'01.05' // Svátek práce
    ,'08.05' // Den vítězství
    ,'05.07' // Cyrila a Metoděj
    ,'06.07' // Jan Hus
    ,'28.09' // Den české státnosti
    ,'28.10' // Vznik samostatného československého státu
    ,'17.11' // Den boje za svobodu a demokracii
    ,'24.12' // Štědrý den
    ,'25.12' // 1. svátek vánoční
    ,'26.12' // 2. svátek vánoční
    ,'31.12' // Silvestr
    );
}

function bakeryClosedDays()
{
    return array(
        '01.01' // Den obnovy českého státu, Nový rok.
    , date('d.m', strtotime("+1 day", easter_date(date('Y')))) // Velikonoční pondělí
    ,'08.05' // Den vítězství
    ,'28.09' // Den české státnosti
    ,'28.10' // Vznik samostatného československého státu
    ,'17.11' // Den boje za svobodu a demokracii
    ,'25.12' // 1. svátek vánoční
    ,'26.12' // 2. svátek vánoční


    ,'23.07' // TEST
//    ,'24.07' // TEST
//    ,'25.07' // TEST
//    ,'26.07' // TEST
//    ,'28.07' // TEST
    );
}

function isFreeDay($timestamp)
{
    return in_array(date('d.m', $timestamp), freeDays());
}

function isBakeryClosed($timestamp)
{
    return in_array(date('d.m', $timestamp), bakeryClosedDays());
}

function isFriday($timestamp)
{
    return date("N", $timestamp) == 5;
}

function isDeadline($timestamp)
{
    return (int)date('H', $timestamp) >= 12;
}

function isWeekend($timestamp)
{
    return date('N', $timestamp) >= 6;
}

function isToday($timestamp)
{
    return  date('d.m.Y') == date('d.m.Y', $timestamp) ;
}

function resetHours($timestamp)
{
    return strtotime(date('Y-m-d', $timestamp));
}

function getOrderDay($timestamp, $postpone_order = false)
{
    if ($postpone_order) {
        $timestamp = strtotime("+1 day", $timestamp);
    }

    if (isWeekend($timestamp)) {
        return getOrderDay(strtotime("next Tuesday", $timestamp));
    }

    if (isFriday($timestamp) && isDeadline($timestamp)) {
        return getOrderDay(strtotime("next Tuesday", $timestamp));
    }

    if(isBakeryClosed($timestamp)) {
        return getOrderDay(strtotime("+2 day", $timestamp));
    }

    if(isFreeDay($timestamp)) {
        return getOrderDay(strtotime("+1 day", $timestamp));
    }

    if (isDeadline($timestamp)) {
        return strtotime("+2 day", $timestamp);
    }

    return $timestamp;
}


$start_timestamp = strtotime('22.07.2022 10:00:00');

print_r(date('d.m.Y H:i:s', getOrderDay($start_timestamp)));

// weekday before 12 +1 day
// weekday after 12 +2 days
// red-letter day +2 days
// saturday-sunday +2 days

Advertisement

Answer

enter image description here

I’d like to share my own solution, which I ended up with.

Maybe, it’ll help someone in the future.

What helped me a ton was drawing all the possible combinations in graphs, then everything became much clearer and easier.

I think most of the code is self-explanatory, I tried to be as verbose with the function names and variables as possible.

function publicHolidays()
{
    return array(
        '01.01' // Den obnovy českého státu, Nový rok.
    , date('d.m', strtotime("-2 day", easter_date(date('Y')))) // Velký pátek
    , date('d.m', strtotime("+1 day", easter_date(date('Y')))) // Velikonoční pondělí
    ,'01.05' // Svátek práce
    ,'08.05' // Den vítězství
    ,'05.07' // Cyrila a Metoděj
    ,'06.07' // Jan Hus
    ,'28.09' // Den české státnosti
    ,'28.10' // Vznik samostatného československého státu
    ,'17.11' // Den boje za svobodu a demokracii
    ,'24.12' // Štědrý den
    ,'25.12' // 1. svátek vánoční
    ,'26.12' // 2. svátek vánoční
    ,'31.12' // Silvestr
    );
}

function bakeryClosedDays()
{
    return array(
        '01.01' // Den obnovy českého státu, Nový rok.
    , date('d.m', strtotime("+1 day", easter_date(date('Y')))) // Velikonoční pondělí
    ,'08.05' // Den vítězství
    ,'28.09' // Den české státnosti
    ,'28.10' // Vznik samostatného československého státu
    ,'17.11' // Den boje za svobodu a demokracii
    ,'25.12' // 1. svátek vánoční
    ,'26.12' // 2. svátek vánoční


//    ,'19.07' // UT - TEST
//    ,'20.07' // ST - TEST
    ,'22.07' // PA - TEST
//    ,'23.07' // SO - TEST
//    ,'25.07' // PO - TEST
    ,'26.07' // TEST
//    ,'27.07' // TEST
//    ,'25.07' // TEST
//    ,'26.07' // TEST
//    ,'28.07' // TEST
    );
}

function isPublicHoliday($timestamp)
{
    return in_array(date('d.m', $timestamp), publicHolidays());
}

function isBakeryClosed($timestamp)
{
    return in_array(date('d.m', $timestamp), bakeryClosedDays());
}

function isAfterOrderHour($timestamp)
{
    return (int)date('H', $timestamp) >= 12;
}

function isWeekend($timestamp)
{
    return date('N', $timestamp) >= 6;
}

function isWorkingDay($timestamp)
{
    if (isWeekend($timestamp)) {
        return false;
    }

    if (isBakeryClosed($timestamp)) {
        return false;
    }

    if (isPublicHoliday($timestamp)) {
        return false;
    }

    return true;
}

function getNextWorkingDay($timestamp)
{
    do {
        $timestamp = strtotime('+1 day', $timestamp);
    } while(!isWorkingDay($timestamp));

    return $timestamp;
}

function getOrderDayTimestamp($orderTimestamp)
{
    if (isAfterOrderHour($orderTimestamp) || !isWorkingDay($orderTimestamp)) {
        $nextOrderOfficeProcessingTimestamp = getNextWorkingDay($orderTimestamp);
        $nextOrderTimestamp = $nextOrderOfficeProcessingTimestamp;
        do {
            $nextOrderTimestamp = strtotime('+1 day', $nextOrderTimestamp);
        } while(isBakeryClosed($nextOrderTimestamp));

        return $nextOrderTimestamp;
    }

    $nextOrderTimestamp = $orderTimestamp;
    do {
        $nextOrderTimestamp = strtotime('+1 day', $nextOrderTimestamp);
    } while(isBakeryClosed($nextOrderTimestamp));

    return $nextOrderTimestamp;
}

$orderTimestamp = strtotime('21.07.2022 10:00:00');
printf("Chosen day | %s", date('l - d.m.Y H:i', $orderTimestamp));
echo "n";

printf("Future order | %s", date('l - d.m.Y H:i', getOrderDayTimestamp($orderTimestamp)));
echo "n";
echo "n";
echo "n";
echo "n";
echo "n";
echo "n";



var_dump(isWorkingDay($orderTimestamp));;

// weekday before 12 +1 day
// weekday after 12 +2 days
// red-letter day +2 days
// saturday-sunday +2 days
User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement