0

I have a very complicated delivery situation with a switch statement that is checking day of the week and a cutoff time of 16:00 everyday and echo's out the delivery day which on Monday, Tuesday and Wednesday is todays day + 1 day if post cut off it should echo todays date + 2, thursdays and fridays have completely different delivery days due to the none delivery on weekends

<?php
    $today = date("D");
        switch($today){
            case "Mon":
            if(mktime(16, 0, 0) <= time()) {
                    echo "<p>For Delivery on <strong> " . date('D jS', strtotime($Date. ' + 2 days')) . "</strong><p>";
                } else {
                    echo "<p>For Delivery on <strong> " . date('D jS', strtotime($Date. ' + 1 days')). "</strong><p>";
                }
                break;
            case "Tue":
                if(mktime(16, 0, 0) <= time()) {
                    echo "<p>For Delivery on <strong> " . date('D jS', strtotime($Date. ' + 2 days')). "</strong><p>";
                } else {
                    echo "<p>For Delivery on <strong> " . date('D jS', strtotime($Date. ' + 1 days')). "</strong><p>";
                }
                break;
            case "Wed":
                if(mktime(16, 0, 0) <= time()) {
                    echo "<p>For Delivery on <strong> " . date('D jS', strtotime($Date. ' + 2 days')). "</strong><p>";
                } else {
                    echo "<p>For Delivery on <strong> " . date('D jS', strtotime($Date. ' + 1 days')). "</strong><p>";
                }
                break;
            case "Thu":
            if(mktime(16, 0, 0) <= time()) {
                    echo "<p>For Delivery on <strong> " . date('D jS', strtotime($Date. ' + 4 days')). "</strong><p>";
                } else {
                    echo "<p>For Delivery on <strong> " . date('D jS', strtotime($Date. ' + 1 days')). "</strong><p>";
                }
                break;
            case "Fri":
                if(mktime(16, 0, 0) <= time()) {
                    echo "<p>For Delivery on <strong> " . date('D jS', strtotime($Date. ' + 5 days')). "</strong><p>";
                } else {
                    echo "<p>For Delivery on <strong> " . date('D jS', strtotime($Date. ' + 4 days')). "</strong><p>";
                }
                break;
            case "Sat":
                    echo "<p>For Delivery on <strong> " . date('D jS', strtotime($Date. ' + 4 days')). "</strong><p>";
                break;
            case "Sun":
                    echo "<p>For Delivery on <strong> " . date('D jS', strtotime($Date. ' + 3 days')). "</strong><p>";
                break;
            default:
                echo "No information available for that day.";
                break;
        }
        ?>

surely they must be a more elegant way of achieving this, would any body know of a cleaner way of achieving the same result. This code works but could be alot better and shorter

Brad Holmes
  • 497
  • 5
  • 22

3 Answers3

2

Note you can stack case matches that do the same thing:

switch ($today) {
    case 'Mon':
    case 'Tue':
    case 'Wed':
        // code here
        break;
}

But you're better off just making a little array that contains the values you need for the days, and then look up today's value by using the day name as the array index:

$leadtimes = [
    'Mon' => [1, 2], // first value is for before 16:00, second is for after
    'Tue' => [1, 2],
    'Wed' => [1, 2],
    'Thu' => [1, 4],
    'Fri' => [4, 5],
    'Sat' => [4, 4],
    'Sun' => [3, 3],
];

Then, the code to calculate the lead time is just one line:

$leadtime = $leadtimes[date('D')][date('H') < 16 ? 0 : 1];

Then plug it into your output as previous:

echo
    "<p>For Delivery on <strong> " .
    date('D jS', strtotime("$Date + $leadtime days")) .
    "</strong><p>";

Now, when you want to change leadtimes, there's no coding to edit, just adjust the value in the array.

And because it's been a while since I've done any code golf, here's the whole thing on a single line:

echo date('D jS',strtotime('+'.['Mon'=>[1,2],'Tue'=>[1,2],'Wed'=>[1,2],'Thu'=>[1,4],'Fri'=>[4,5],'Sat'=>[4,4],'Sun'=>[3,3]][date('D')][date('H')<16].'day'));
Alex Howansky
  • 50,515
  • 8
  • 78
  • 98
  • `strtotime($Date . ' + " . $leadtime days"))` this doesnt look correct to me are you sure about this? – Brad Holmes Jan 18 '19 at 22:02
  • (I note that `$Date` isn't set anywhere in your code, I'm assuming you've got it set elsewhere. If `$Date` is always "now" then you can just leave out the `$Date` part and use `strtotime("+ $leadtime days")`. – Alex Howansky Jan 18 '19 at 22:06
1

A quick attempt would be as I mentioned in the comment, remove the repeating code, this is both the string used to echo and also being able to organise the switch so that any days with common values are all processed by the same code...

$today = date("D");
switch($today){
    case "Mon":
    case "Tue":
    case "Wed":
        $days = (mktime(16, 0, 0) <= time())? 2 : 1;
        break;
    case "Thu":
        $days = (mktime(16, 0, 0) <= time())? 4 : 1;
        break;
    case "Fri":
        $days = (mktime(16, 0, 0) <= time())? 5 : 4;
        break;
    case "Sat":
        $days = 4;
        break;
    case "Sun":
        $days = 3;;
        break;
    default:
        break;
}
if ( isset($days) ) {
    echo "<p>For Delivery on <strong> " . date('D jS', strtotime($Date. " + {$days} days")). "</strong><p>";
}
else    {
    echo "No information available for that day.";
}
Nigel Ren
  • 56,122
  • 11
  • 43
  • 55
0

How about this:

$today = date("D");
$cutoff = mktime(16, 0, 0) <= time();

$offset = $cutoff ? 2 : 1;
$offset = $cutoff and $today === 'Thu' ? 4 : 1;
$offset = $cutoff and $today === 'Fri' ? 5 : 4;
$offset = $today === 'Sat' ? 4 : $offset;
$offset = $today === 'Sun' ? 3 : $offset;

echo "<p>For Delivery on <strong> " . date('D jS', strtotime("$Date $offset days")) . "</strong><p>";

Also I'd suggest using Carbon for working with dates.

  • This is really nice, this is the cleanest but it requires thursday post 16:00 to 4 days and friday pre 16:00 to be 3 days post 16:00 to be 4 days – Brad Holmes Jan 18 '19 at 16:31
  • I would check the results, it will return 3 for virtually everything. – Nigel Ren Jan 18 '19 at 16:47
  • @BradHolmes Fixed it. –  Jan 18 '19 at 16:51
  • @NigelRen Only if today equals sunday or am I missing something? –  Jan 18 '19 at 16:52
  • If the day isn't Sunday - how does the previous value of `$offset` get kept? – Nigel Ren Jan 18 '19 at 16:55
  • @NigelRen If today is not sunday, then $today === 'Sun' would be false and then $offset would not be changed. ?: is short for ? 4 : $offset. –  Jan 18 '19 at 16:59
  • Please read https://stackoverflow.com/questions/1993409/operator-the-elvis-operator-in-php - `$today === 'Sun' ?: 3` is short for `$today === 'Sun' ? $today === 'Sun' : 3` – Nigel Ren Jan 18 '19 at 17:00
  • @NigelRen My bad. Fixed it. –  Jan 18 '19 at 17:06
  • this is currently returning today +1 for everything for some reason – Brad Holmes Jan 18 '19 at 21:31
  • @BradHolmes You're right. Guess I should've tested it. Seems like I'm missing some conditions for $cutoff being false but at this point my approach becomes less readable than a switch case. I'd still put the cutoff condition into a variable, though. –  Jan 18 '19 at 23:18