Home > Blockchain >  How to make a code that finds sundays when date picked a start date and end date in PHP
How to make a code that finds sundays when date picked a start date and end date in PHP

Time:09-07

I'm currently working on a project (membership system) with a start date and expiration date. For example the user chose the 30 days membership and his starting date is Sep, 05,2022. So 09/05/2022 30 days is equals to expiration date. But I want to skip sundays when adding the 30 days in the starting date. How can I do that in PHP?

CodePudding user response:

I would use a loop. It's also a great start if you're going to extend that to holidays. Otherwise, it is an overkill but I really don't think you'd suffer performance issues.

So here we go:

$start_date = "2022-09-05";
$start = new DateTime($start_date);
$days = 30;
while ($days) {
    
    // P1D means a period of 1 day
    $start->add(new DateInterval('P1D')); 
    $day = $start->format('N');

    // 7 = sunday
    if ($day != 7) {
        $days--;
    } 
}
print_r($start);

// output:
// [date] => 2022-10-10 00:00:00.000000

CodePudding user response:

Full weeks should be pre-calculated for better performance. The following function allows you to name one or more days of the week that are not counted.

 /**
  * Add days without specific days of the week
  * 
  * @param DateTime $startDate      start Date
  * @param int $days                number of days
  * @param array $withoutDays       array with elements "Mon", "Tue", "Wed", "Thu", "Fri", "Sat","Sun"
  * @return DateTime 
  */ 
function addDaysWithout(DateTime $startDate ,int $days, array $withoutDays = []) : DateTime
{
  //validate $withoutDays
  $validWeekDays = 7 - count($withoutDays);
  $validIdentifiers = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat","Sun"];
  if($validWeekDays <= 0 OR
    $withoutDays != array_intersect($withoutDays,$validIdentifiers)){
      $msg = 'Invalid Argument "'.implode(',',$withoutDays).'" in withoutDays';
      throw new \InvalidArgumentException($msg); 
  } 
  $start = clone $startDate;
  $fullWeeks = (int)($days/$validWeekDays)-1;
  if($fullWeeks > 0){
    $start ->modify($fullWeeks.' weeks');
    $days -= $fullWeeks * $validWeekDays;
  }
  while($days){
    $start->modify(' 1 Day');
    if(!in_array($start->format('D'),$withoutDays)){
      --$days;
    }
  }
  return $start;
}

Application examples:

$start = date_create('2022-09-05'); 
$dt = addDaysWithout($start,30,["Sun"]);
var_dump($dt); 
//object(DateTime)#3 (3) { ["date"]=> string(26) "2022-10-10 00:00:00.000000"

$start = date_create('2022-09-05'); 
$dt = addDaysWithout($start,30,["Mon","Sun"]);
var_dump($dt); 
//object(DateTime)#3 (3) { ["date"]=> string(26) "2022-10-15

Demo: https://3v4l.org/AZX0E

  • Related