Home > Software engineering >  how to return an arrays of the free days using DateTime
how to return an arrays of the free days using DateTime

Time:01-04

I'm using Laravel 9 to create lessons scheduler,

I tried that way but Im little lost,

$free_time_frame = [[]];  // nested array here

$start = new DateTime("2023-01-01");
$end = new DateTime("2023-12-31");

$interval = new DateInterval("P1D"); // 1 month interval
$period = new DatePeriod($start, $interval, $end);
$seasons = ["2023-02-01", "2023-02-13"];
foreach ($period as $date) {
  if (in_array($date->format("Y-m-d"), $seasons)) {
    // Skip the rest of the loop if the current month is in the $seasons array
    $free_time_frame[] = [];   // append nested array
    continue;
  }

  // Set the start date to the first day of the month
  $start_date = new DateTime($date->format("Y-m-01"));
  // Set the end date to the last day of the month
  $end_date = new DateTime($date->format("Y-m-t"));

  // Calculate the number of days between the start and end dates
  $diff = $start_date->diff($end_date);
  $days = $diff->days   1; // Add 1 to include the end date

  // use the latest nested array
  

}

I'm booking $seasons I would like to have an array of the free days before "2023-02-01" and days after "2023-02-13" like that :

Expected Result

[
  [
   "2023-01-01",
   "2023-01-02",
   "2023-01-03",
   "..."
   "2023-01-31",
  ]
  [
   "2023-02-14",
   "2023-02-15",
   "2023-02-16",
   "2023-02-14",
   "and so on util the end of the year"
  ]
]

Thanks for the help in advance

CodePudding user response:

Okay, so I think I understand, that you want to get all dates between a range of dates, then exclude a specific range of date.

You can do it like this:

$originalDates = \Carbon\CarbonPeriod::between('2023-01-01', '2023-01-10')->toArray();
$excludedDates = \Carbon\CarbonPeriod::between('2023-01-03', '2023-01-06')->toArray();
        
$finalDates = [];
        
foreach ($originalDates as $date) {
    if(!in_array($date, $excludedDates)){
        array_push($finalDates, $date->format('d-m-Y'));
    }
}
    
return $finalDates;

This will return an array of the following results:

01-01-2023
02-01-2023
07-01-2023
08-01-2023
09-01-2023
10-01-2023

Notice here that it skipped over from 2023-01-03 to 2023-01-06

You can format this as you like by changing the line of $date->format('d-m-Y') to represent the results the way you want it, you can even remove the format to return a carbon array, which you can parse as you like somewhere else.

And you can go one step further, and have multiple excludedDates, and check for them in_array

Hopefully this helps, add a comment if you want further clarifications or modifications.

CodePudding user response:

To calculate free time from $seasons that doesn't include in-between time period, it is just the everything before your first element of your seasons array and everything after last element of your seasons array.

So, achieving this is just running 2 loops of DatePeriod in those ranges.

<?php

$seasons = ["2023-02-01", "2023-02-13", "2023-03-16"];

$free_time_frame = [];

$free_time_frame[] = getDaysInPeriod('2023-01-01', 'P1D', current($seasons));
$free_time_frame[] = getDaysInPeriod(date("Y-m-d", strtotime(end($seasons). "  1 days")), 'P1D', '2024-01-01');


function getDaysInPeriod($startDate, $dateInterval, $endDate){
  $span = [];
  foreach(new DatePeriod(new DateTime($startDate), new DateInterval($dateInterval),new DateTime($endDate)) as $p){
    $span[] = $p->format('Y-m-d');
  }
  return $span;
}

$free_time_frame = array_filter($free_time_frame);

print_r($free_time_frame);

Online Fiddle

CodePudding user response:

        $a = new DateTime("2023-01-01");
        $b = new DateTime("2023-12-31");
        $book = ["2023-01-03", "2023-01-07"];

        $freeDays = [];
        $currentGroup = [];

        while ($a <= $b) {
            if (in_array($a->format('Y-m-d'), $book)) {
                $freeDays[] = $currentGroup;
                $currentGroup = [];
            } else {
                $currentGroup[] = $a->format('Y-m-d');
            }
            $a->modify(' 1 day');
        }

        $freeDays[] = $currentGroup;

        return $freeDays;

CodePudding user response:

$a = new DateTime("2023-01-01");
$b = new DateTime("2023-12-31");
$book = ["2023-01-03", "2023-01-07"];

$freeDays = [];
$currentGroup = [];

while ($a <= $b) {
  if (in_array($a->format('Y-m-d'), $book)) {
    $freeDays[] = $currentGroup;
    $currentGroup = [];
  } else {
    $currentGroup[] = $a->format('Y-m-d');
  }
  $a->modify(' 1 day');
}

$freeDays[] = $currentGroup;

$firstBooking = reset($book);
$lastBooking = end($book);

$firstIndex = array_search($firstBooking, array_column($freeDays, 0));
$lastIndex = array_search($lastBooking, array_column($freeDays, 0));

array_splice($freeDays, $firstIndex   1, $lastIndex - $firstIndex - 1);

return $freeDays;
  • Related