skip to Main Content

I have to iterate on multiple dates intervals: -for example:

  1. 09/06/2023 – 15/06/2023
  2. 28/05/2023 – 02/06/2023
  3. 17/06/2023 – 18/06/2023
  4. 29/06/203 – 04/07/2023
    …etc

I need to obtain day numbers for only one given month: in this case June (06).

In theory I should obtain an array like this: var june = [09,10,11,12,13,14,15,01,02,17,18,29,30];

Steps taken by me:

a. in php query to take all departing, returning dates and number of date intervals as arrays (they are string Arrays, not Date object, integer in case of date interval numbers)

b. create arrays of departing and returning dates in javascript: var departure, var rback, var number

c. define empty array of days:

var days=[];

d. loop through all date intervals in order to obtain all dates in between the intervals

function enumerateDaysBetweenDates(startDate, endDate) {
        startDate = moment(startDate,"DD/MM/YYYY");
        endDate = moment(endDate,"DD/MM/YYYY");
    
        var now = startDate, dates = [];
    
        while (now.isBefore(endDate) || now.isSame(endDate)) {
            dates.push(now.format("DD/MM/YYYY"));
            now.add(1, 'days');
        }
        return dates;
    };

 for (i = 0; i < number.length; i++) {
    
    var mdepart=departure[i];
    var mrback=rback[i];
    
    
    
    days.push(enumerateDaysBetweenDates(mdepart,mrback));
    
    };

Now I need to filter all dates that are not in June:

function checkd(num) {
  return num.includes("/06/");
};
 
var june=days.filter(checkd);

The problem: when I run this I obtain an error "days.filter is not a function"…

If I run it like this: var june = Object.values(days).filter(checkd); I have an empty array…

I don’t know where is the problem: maybe because I have dates arrays elements defined as strings at first and using moment.js I have them now as dates?

complete code:

var days=[];
var number=[1,2,3,4];
var departure=[09/06/2023,28/05/2023, 17/06/2023, 29/06/2023];
var rback=[15/06/2023,02/06/2023,18/06/2023,04/07/2023];

function enumerateDaysBetweenDates(startDate, endDate) {
        startDate = moment(startDate,"DD/MM/YYYY");
        endDate = moment(endDate,"DD/MM/YYYY");
    
        var now = startDate, dates = [];
    
        while (now.isBefore(endDate) || now.isSame(endDate)) {
            dates.push(now.format("DD/MM/YYYY"));
            now.add(1, 'days');
        }
        return dates;
    };

for (i = 0; i < number.length; i++) {
    
    var mdepart=departure[i];
    var mrback=rback[i];
    
    
    
    days.push(enumerateDaysBetweenDates(mdepart,mrback));
    
    };

//Now I need to filter all dates that are not in June:

function checkd(num) {
  return num.includes("/06/");
};
 
var june=days.filter(checkd);

//Error days.filter or empty array....
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>

2

Answers


  1. Please avoid using Moment; use Luxon instead. The API is slightly different, but the library is immutable and recommended. It is created by the same team as Moment.

    Checkout this post for more information on JavaScript date/time libraries:

    JavaScript format date / time

    Now, if you want to collect the days within a particular month, the easiest approach would be to convert the raw data into data ranges. After you have the ranges, you can traverse them and increment the start date until it is equal to the end date.

    Please note that I use the month index, rather than the number that represents the month. The built-in JavaScript Date object refers to months by their index. You may change this logic if it bothers you.

    Also, I did not factor-in a year. So the code assumes that the dates all occur within the same year.

    const { DateTime } = luxon;
    
    const data = [
      '09/06/2023 - 15/06/2023',
      '28/05/2023 - 02/06/2023',
      '17/06/2023 - 18/06/2023',
      '29/06/2023 - 04/07/2023'
    ];
    
    const dateFormat = 'dd/MM/yyyy';
    
    const parseDate = (timestamp, format) =>
      DateTime.fromFormat(timestamp, format); // Luxon parse
    
    const ranges = data.map(item =>
      item
        .split(/s*-s*/)
        .map(timestamp => parseDate(timestamp, dateFormat)));
    
    const daysInMonth = (ranges, monthIndex) => {
      const days = new Set();
      let currDate;
      for (let [startDate, endDate] of ranges) {
        currDate = startDate;
        while (currDate <= endDate) {
          if (currDate.month - 1 === monthIndex) {
            days.add(currDate.day);
          }
          currDate = currDate.plus({ days: 1 }); // Increment to next day
        }
      }
      return [...days]; // Could also call: .toSorted((a, b) => a - b)
    }
    
    const days = daysInMonth(ranges, 5); // June is the 5th index
    
    console.log(...days); // 9 10 11 12 13 14 15 1 2 17 18 29 30
    .as-console-wrapper { top: 0; max-height: 100% !important; }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/luxon/3.3.0/luxon.min.js"></script>
    Login or Signup to reply.
  2. With the date strings always in the dd/mm/yyyy format you can use a few array methods including Array#filter to get the June dates as follows:

    const data = [
      '09/06/2023 - 15/06/2023',
      '28/05/2023 - 02/06/2023',
      '17/06/2023 - 18/06/2023',
      '29/06/2023 - 04/07/2023'
    ],
    
    searchMo = '06',
    
    searchDays = data.flatMap(
        range => range.split(' - ')
        .filter(date => date.split('/')[1] === searchMo)
        .map(date => date.split('/')[0])
    );
    
    
    console.log( searchDays );
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search