Search code examples
javascriptarraysjsonlodash

JSON with counts for all occurrences for all dates between a from and to date


I have the following array of objects

const monthlyList =  [
       {
          "leave_id":119,
          "employee_id":"25528",
          "from_date":"2022-03-10",
          "to_date":"2022-03-11",
          "employee_name":"Name 1"
       },
       {
          "leave_id":120,
          "employee_id":"25529",
          "from_date":"2022-03-10",
          "to_date":"2022-03-13",
          "employee_name":"Name 2"
       },
       {
          "leave_id":121,
          "employee_id":"25530",
          "from_date":"2022-03-15",
          "to_date":"2022-03-18",
          "employee_name":"Name 3"
       },
       {
          "leave_id":123,
          "employee_id":"25530",
          "from_date":"2022-03-20",
          "to_date":"2022-03-20",
          "employee_name":"Name 3"
       }
    ]

I am trying to display the count of leave events for each day in a calendar using FullCalendar. For this, I am trying to get an array in the following format

[
   {
      "date":"2022-03-10",
      "count":2
   },
   {
      "date":"2022-03-11",
      "count":2
   },
   {
      "date":"2022-03-12",
      "count":1
   }
   --- etc
]

That is if there are two leaves are there on the same date, the count should be 2. Also, it should calculate the count for all the dates between the from_date and to_date so that I can display the count on the calendar for all the dates that fall between the range.

I use the following code using lodash to group based on from_date and to_date and from there I can create the array above. But not sure how to do it for the days in between

let groupedListFrom = _.groupBy(monthlyList, "from_date");
let groupedListTo   = _.groupBy(monthlyList, "to_date");

It will be really helpful if someone can help me here. Thanks


Solution

  • A possible approach using reduce rather than Lodash.
    I used https://gist.github.com/miguelmota/7905510 as a helper to get Date objects between two given dates.

    const monthlyList =  [
           {
              "leave_id":119,
              "employee_id":"25528",
              "from_date":"2022-03-10",
              "to_date":"2022-03-11",
              "employee_name":"Name 1"
           },
           {
              "leave_id":120,
              "leave_id":"25529",
              "from_date":"2022-03-10",
              "to_date":"2022-03-13",
              "employee_name":"Name 2"
           },
           {
              "leave_id":121,
              "employee_id":"25530",
              "from_date":"2022-03-15",
              "to_date":"2022-03-18",
              "employee_name":"Name 3"
           },
           {
              "leave_id":123,
              "employee_id":"25530",
              "from_date":"2022-03-20",
              "to_date":"2022-03-20",
              "employee_name":"Name 3"
           }
        ]
     
     //a function to get Date objects between two given dates (inclusive)
     //https://gist.github.com/miguelmota/7905510
     const getDates = (startDate, endDate) => {
      const dates = []
      let currentDate = startDate
      const addDays = function (days) {
        const date = new Date(this.valueOf())
        date.setDate(date.getDate() + days)
        return date
      }
      while (currentDate <= endDate) {
        dates.push(currentDate)
        currentDate = addDays.call(currentDate, 1)
      }
      return dates
    }
    
    
    let x = Object.values(monthlyList.reduce((acc,{leave_id,employee_id,from_date,to_date,employee_name})=>{
        const dates = getDates(new Date(from_date), new Date(to_date));
      dates.forEach((date) => {
        let strippedDate = date.toISOString().substring(0,10);
        if(!acc[strippedDate])acc[strippedDate]={date:strippedDate,count:0};
        acc[strippedDate].count+=1
    
        })
      return acc;
      
    },{}))
    
    console.log(x)