-1

I have a site where it calculates the delivery dates for orders. so we have days starting fro 1 to 30 So the main conditions are,

  • if someone places an order on Saturday or Sunday, the days should start from Monday (working days are Monday to Friday)
  • if someone places an order before 18.00 then the days should start from today or else if should start from the next day.. eg: if the order was place on 2020-07-07 before 18.00, then 7th is the starting day or else its the 8th
  • if the delivery date falls on Sunday then it should move to Monday

Below is my code, the problem is that it works only on certain days. Most of the time it adds an extra day.

$thedays = array('1','2','3','4','5');

foreach ($thedays as $days) {

if (date('H') > 17) {
   $cutoff = 1;

} else {
     $cutoff = 0;
}


$extra_days = 0;

//is today a weekend
if(date('l', strtotime(date('Y-m-d'))) == 'Sunday')  {
    
    $extra_days = 1;
}

if(date('l', strtotime(date('Y-m-d'))) == 'Saturday')  {
    
    $extra_days = 2;
}

$total1= $cutoff+$extra_days+$days;

$date_1 = date('Y-m-d', strtotime("+".$total1." day"));

 $date = date('Y-m-d');
 $date2 = $date_1;

$period = new DatePeriod(
    new DateTime($date),
    new DateInterval('P1D'),
    new DateTime($date2)
);


$q = 0;
$d= 0;
foreach ($period as $key => $value) {
    $d++;
    if ($value->format('N') > 5) {
       $q++;
       
    }  
}


$total_days_with_weekends = ($days+$q+$extra_days);

$date_1 = date('Y-m-d', strtotime("+".$total_days_with_weekends." day"));

if(date('l', strtotime($date_1)) == 'Saturday')  {
 
    $date_1 = date('Y-m-d', strtotime("-1 day"));
}


if(date('l', strtotime($date_1)) == 'Sunday')  {
    $days= $days+1;
    
    $date_1 = date('Y-m-d', strtotime("+".$days." day"));
    
}

echo $data_1;

}

Can someone suggest a best way to do this?

Thanks

LiveEn
  • 3,193
  • 12
  • 59
  • 104

1 Answers1

0

Considering Saturday as also not valid delivery date i got something like this:

function getDeliveryDate(DateTime $orderDate, int $days): DateTime {
  $deliveryDate = clone $orderDate;
  $remainingDays = $days;

  // if it is after 18:00 we skip current day
  if ($orderDate->format('H') >= 18) {
    $deliveryDate->add(new DateInterval('P1D'));
  }

  // we process days until we reach specified amount
  while ($remainingDays > 0) {
    $deliveryDate->add(new DateInterval('P1D'));

    // we skip saturday and sunday
    if (!in_array($deliveryDate->format('D'), ['Sat', 'Sun'])) {
      $remainingDays--;
    }
  }

  return $deliveryDate;
}

Can be simplified with weekday:

function getDeliveryDate(DateTime $orderDate, int $days): DateTime {
  $deliveryDate = clone $orderDate;

  if ($orderDate->format('H') >= 18) {
    $days++;
  } 
  
  return $deliveryDate->modify('+'.$days.' weekday');
}

Tests:

function check(string $orderDate, int $days, string $expectedDeliveryDate) {
  $deliveryDate = getDeliveryDate(new DateTime($orderDate), $days);

  if ($deliveryDate->format('Y-m-d') !== $expectedDeliveryDate) {
    echo 'Order date: '.$orderDate.', days: '.$days.', expected: '.$expectedDeliveryDate.' got: '.$deliveryDate->format('Y-m-d').PHP_EOL;
  } else {
    echo 'Order date: '.$orderDate.', days: '.$days.', expected: '.$expectedDeliveryDate.' - OK'.PHP_EOL;
  }
}

check('2020-07-08 12:00', 1, '2020-07-09');
check('2020-07-08 12:00', 2, '2020-07-10');
check('2020-07-08 18:00', 1, '2020-07-10');
check('2020-07-08 12:00', 6, '2020-07-16');
check('2020-07-08 12:00', 5, '2020-07-15');

Tests output:

Order date: 2020-07-08 12:00, days: 1, expected: 2020-07-09 - OK
Order date: 2020-07-08 12:00, days: 2, expected: 2020-07-10 - OK
Order date: 2020-07-08 18:00, days: 1, expected: 2020-07-10 - OK
Order date: 2020-07-08 12:00, days: 6, expected: 2020-07-16 - OK
Order date: 2020-07-08 12:00, days: 5, expected: 2020-07-15 - OK
blahy
  • 1,294
  • 1
  • 8
  • 9