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:
- 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.
- 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.
- 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.
- 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.
- 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.
- 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.
- 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
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