0

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>
GigiF
  • 81
  • 5
  • 4
    Don't break it up, show the code as one, complete, runnable snippet, so that folks (but also, you yourself) can verify that what you're saying it does is indeed what's happening. – Mike 'Pomax' Kamermans Aug 18 '23 at 15:11
  • `days = [...days, ...enumerateDaysBetweenDates(mdepart,mrback)];` – M0nst3R Aug 18 '23 at 15:19
  • No, don't duplicate it, just show the complete code as runnable snippet (not just a code block, click the runnable snippet button so it can literally be run in your post, with a console log at the end to show the result =) and then update the post so that you're talking about what happens in that without quoting code. – Mike 'Pomax' Kamermans Aug 18 '23 at 15:24
  • 1
    you've enclosed your "rback" array declaration with a curly bracket } instead of a normal one ] – Richard Aug 18 '23 at 15:27
  • @GigiF I tried your code with my suggestion above, seems to solve the issue you're having. Also, I am not able to reproduce the "_days.filter is not a function_" problem because `days` is actually an array here. – M0nst3R Aug 18 '23 at 15:33

2 Answers2

1

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 );
PeterKA
  • 24,158
  • 5
  • 26
  • 48
0

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>
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
  • 1
    Works great! - thank you! - I did not know about Luxon....I also appreciate the comments for code. – GigiF Aug 18 '23 at 16:47