skip to Main Content

I am trying to create an array of months that have nested arrays with all the days in that month between a date range in JavaScript with MomentJS.

aiming to achieve: if my date range was May 1st – June 3rd

Using this loop i can successfully build an array of days but i cannot split them into months..

while (currentDate <= endDate) {
currentDate.setDate(currentDate.getDate() + 1);
dates.push(new Date(currentDate));

This is pretty much what i want to achieve:

[May - month name
1st May - date object for day
2nd May
3rd May
4th May
...]
June
[1st June
2nd June
3rd June]

Any help would be appreciated!

2

Answers


  1. You can use plain; vanilla JavaScript without any libraries to accomplish this. The Intl library provides an API for display time/date and number formats based on a locale.

    const
      monthFrmt = new Intl.DateTimeFormat('en', { month: 'long' }),
      startDate = new Date('2023-05-01T00:00:00'), // May 1st
      endDate = new Date('2023-07-03T00:00:00'),   // June 3rd (inclusive)
      dateFormatterFn = (date) => `${monthFrmt.format(date)} ${ordinal(date.getDate())}`;
    
    const main = () => {
      const dates = generateDates(startDate, endDate, dateFormatterFn);
      console.log(dates);
    };
    
    const generateDates = (startDate, endDate, dateFormatterFn) => {
      const results = [], currDate = new Date(startDate.getTime());
      while (currDate <= endDate) {
        const key = monthFrmt.format(currDate);
        if (results[results.length - 1]?.key !== key) results.push({ key, values: [] });
        results[results.length - 1].values.push(dateFormatterFn(currDate));
        currDate.setDate(currDate.getDate() + 1);
      }
      return results.map(Object.values);
    }
    
    const rules = new Intl.PluralRules('en', { type: 'ordinal' });
    const suffixes = { one: 'st', two: 'nd', few: 'rd', other: 'th' };
    const ordinal = (number) => `${number}${suffixes[rules.select(number)]}`;
    
    main();
    .as-console-wrapper { top: 0; max-height: 100% !important; }
    Login or Signup to reply.
  2. You could try something like this. A function for collecting the days between two days, and nother for grouping by month (you need year as well then).

    const collectDays = (start, stop) => {
        let cursor_mut = start, out = [];
    
        while (cursor_mut <= stop) {
            cursor_mut.setDate(cursor_mut.getDate() + 1);
            out.push(new Date(cursor_mut));
        }
    
        if (start > stop) {
            return [out, true];
        } else {
            return [out, false];
        }
    };
    
    
    const groupDays = (dates) => {
        let grouped = {};
        
        for (let d of dates) {
            let key = JSON.stringify([d.getFullYear(), d.getMonth()]);
            if (!grouped[key]) {
                grouped[key] = [];
            }
            grouped[key].push({ year: d.getFullYear(), month: d.getMonth(), day: d.getDate() });
        }
        
        return grouped;
    };
    
    
    let startDate = new Date();
    let endDate = new Date();
    endDate.setDate(endDate.getDate() + 90);
    let outArray = [];
    let result = collectDays(startDate, endDate, outArray);
    console.log(result);
    let groupedDates = groupDays(result[0]);
    console.log(groupedDates);
    

    https://jsfiddle.net/xpz43rog/1

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