skip to Main Content

I have a list of dates in my database table

e.g.

"2023-12-03"
"2023-12-10"
"2023-12-17"
"2024-01-07"
"2024-01-14"
"2024-01-21"

I need this to be returned to front end in the following form:

[1]=>
array(2) {
  ["year"]=>
  string(4) "2024"
  ["months"]=>
  array(3) {
   [0]=>
    array(2){
        ["monthName"]=>
        string(4) "January"
        ['paid'] = //to be set 
        ["dates"]=>
            array(4) {
            [0]=>
            string(10) "2024-01-07"
            [1]=>
            string(10) "2024-01-14"
            [2]=>
            string(10) "2024-01-21"
            [3]=>
            string(10) "2024-01-28"
            }
    }

I have managed to sort the dates by year and months but my problem is that the months array keys are the months names instead of numbered indexes:

    $reserved_dates = array(
        '2023-12-03',
        '2023-12-10',
        '2023-12-17',
        '2023-12-24',
        '2023-12-31',
        '2024-01-07',
        '2024-01-14',
        '2024-01-21',
        '2024-01-28',
        '2024-02-04',
        '2024-02-11',
        '2024-02-18',
        '2024-02-25',
        '2024-12-01',
        '2023-12-03',
        '2024-12-08',
        '2024-12-15',
    );

    $years = Array();
    foreach($reserved_dates as $date) {
        $d = $date['date'];
        list($y,$m) = explode("-",$d);
        $years[$y][] = $d;
    }
    $years = array_values($years);

    foreach($years as $year)
    {
        $year_number = date('Y', strtotime($year[0]));

        $new = array(
            "year" => $year_number,
            "months" => array()
        );

        foreach($year as $month)
        {
            $month_name = date('F', strtotime($month));

            if(!isset($new['months'][$month_name]))
            {
                $new['months'][$month_name] = array();
            }

            array_push($new['months'][$month_name], $month);
        }

        array_push($reservation['reservedDates'], $new);
    }




array(2) {
    [0]=>
    array(2) {
      ["year"]=>
      string(4) "2023"
      ["months"]=>
      array(1) {
        ["December"]=>
        array(5) {
          [0]=>
          string(10) "2023-12-03"
          [1]=>
          string(10) "2023-12-10"
          [2]=>
          string(10) "2023-12-17"
          [3]=>
          string(10) "2023-12-24"
          [4]=>
          string(10) "2023-12-31"
        }
      }
    }

2

Answers


  1. If you want months array key are number index instead of months name then you can achieve this by using the array_values function for re indexing month array.

    Also, inside your reserved_dates loop you access date from date array but reserved_dates have values not key available.

    Please try below code.

    <?php
        $reserved_dates = [
        "2023-12-03",
        "2023-12-10",
        "2023-12-17",
        "2023-12-24",
        "2023-12-31",
        "2024-01-07",
        "2024-01-14",
        "2024-01-21",
        "2024-01-28",
        "2024-02-04",
        "2024-02-11",
        "2024-02-18",
        "2024-02-25",
        "2024-12-01",
        "2024-12-08",
        "2024-12-15",
    ];
    
    $years = [];
    foreach ($reserved_dates as $date) {
        $d = $date;
        list($y, $m) = explode("-", $d);
        $years[$y][] = $d;
    }
    $years = array_values($years);
    
    $reservation = ["reservedDates" => []];
    
    foreach ($years as $year) {
        $year_number = date("Y", strtotime($year[0]));
    
        $new = [
            "year" => $year_number,
            "months" => [],
        ];
    
        foreach ($year as $month) {
            $month_name = date("F", strtotime($month));
    
            if (!isset($new["months"][$month_name])) {
                $new["months"][$month_name] = [
                    "monthName" => $month_name,
                    "dates" => [],
                ];
            }
    
            array_push($new["months"][$month_name]["dates"], $month);
        }
    
        // re indexing month array
        $new["months"] = array_values($new["months"]);
    
        array_push($reservation["reservedDates"], $new);
    }
    
    echo "<pre>";
    print_r($reservation);
    ?>
    
    Login or Signup to reply.
  2. Collect the dates by year and by month in an associative array/map. Now, go to each month inside the associative array individually and usort them. This way, the sorting cost would be minimal when compared to sorting the entire dataset and comparing dates with other dates who don’t even belong to the same bucket!

    Finally, do array_values on the map to remove the hash indexes(like year or months used as integers).

    Snippet:

    <?php
    
    $data = [];
    
    foreach($reserved_dates as $d){
        list($year, $month) = explode("-", $d);
        $data[ $year ]['year'] = $year;
        $data[ $year ]['months'][ $month ] = $data[ $year ]['months'][ $month ] ?? [];
        $data[ $year ]['months'][ $month ]['monthName'] = date("F", strtotime($d));
        $data[ $year ]['months'][ $month ]['paid'] = true; // or false whatever
        $data[ $year ]['months'][ $month ]['dates'] = $data[ $year ]['months'][ $month ]['dates'] ?? [];
        $data[ $year ]['months'][ $month ]['dates'][] = $d;
    }
    
    
    foreach($data as &$months){
        foreach($months['months'] as &$each_month){
            usort($each_month['dates'], fn($a, $b) => DateTime::createFromFormat('!Y-m-d', $a) <=> DateTime::createFromFormat('!Y-m-d', $b));
        }
        $months['months'] = array_values($months['months']);
    }
    
    $data = array_values($data);
    
    print_r($data);
    

    Live Demo

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search