Home > Enterprise >  Split month into first and second half based on current date and return weekdays (JS)
Split month into first and second half based on current date and return weekdays (JS)

Time:07-07

perhaps someone can give me some good ideas of how to accomplish this.

I would like to get the weekdays for either the first two weeks or last two weeks of a month based on the current date.

So if we are using the following to get the date today (2022-07-06)

    const current = new Date();
    const date = `${current.getFullYear()}-${current.getMonth() 1}-${current.getDate()}`;

The results I would be looking for are

const firstHalfWeekdates = ['2022-07-04', '2022-07-05', '2022-07-06', '2022-07-07', '2022-07-08', '2022-07-11', '2022-07-12', '2022-07-13', '2022-07-14', '2022-07-15']

and if the date fell on 2022-07-18 it would return

const secondHalfWeekdates = ['2022-07-18', '2022-07-19', '2022-07-20', '2022-07-21', '2022-07-22', '2022-07-25', '2022-07-26', '2022-07-27', '2022-07-28', '2022-07-29']

Also happy to use a library

CodePudding user response:

Maybe this can give you a start. It returns the weekdays, divided by week.

I was trying to do everything you asked, but I ran into some problems, for example you want to divide the month into 4 weeks, 2 in the first half and 2 in the second half, but for example this month now July/2022, has a week that has only one weekday (July 1º), but in your expected results you ignored this week, whats the logic to ignore weeks? It has to be a complete week with 5 weekdays? What about last month Jun/2022, there were not 4 complete weeks, there were only 3 complete weeks, the other 2 has 3 and 4 days respectively, which week would you ignore in this case?

function isWeekDay(day) {
    return day != 0 && day != 6;
}

function formatDateYYYYMMDD(date) {
    let dateString = date.toLocaleDateString('en-GB');
    let year = dateString.substring(6, 10);
    let month = dateString.substring(3, 5);
    let day = dateString.substring(0, 2);
    return `${year}-${month}-${day}`;
}

function getWeekdaysOfTheCurrentMonthDividedByWeek() {
    let currentDate = new Date();
    let month = currentDate.getMonth();
    let weekdays = [];
    let tempDate = new Date(currentDate.getFullYear(), currentDate.getMonth(), 1);
    let week = [];

    while (tempDate.getMonth() == month) {
        if (isWeekDay(tempDate.getDay())) {
            week.push(formatDateYYYYMMDD(tempDate));
        } else if (week.length > 0) {
            weekdays.push(week);
            week = [];
        }
        tempDate.setDate(tempDate.getDate()   1);
    }

    return weekdays;
}

console.log(getWeekdaysOfTheCurrentMonthDividedByWeek());

CodePudding user response:

You could split the month up into calendar weeks. (e.g. for July 2022 it would be: July 1-2, 3-9, 10-16, ect…)

Then, depending on the day, take either the first or second half of the weeks.

Iterate over the filtered weeks, counting the weekdays.

I choose to include the third week in the first half of the month if there were 5 weeks, but you could change that by changing Math.ceil to Math.floor

/**
 * Get the last item in an array, or undefined if the array is empty.
 * @template T
 * @param {[T]} array
 * @returns {T|undefined}
 */
const lastItem = array => array[array.length - 1];

const getWeekdays = current => {
    /** @type {[[Date]]} */
    const weeks = [];

    // Get the weeks
    /**
     * Get the calendar week of the given date.
     * @param {Date} firstDay The first day of the week.
     * @returns {[Date]}
     */
    const getWeek = firstDay => {
        /** @type {[Date]} */
        let days = [];

        let dateToTest = new Date(firstDay);
        // Continue until the end of the week or month, whichever comes first.
        while (
            dateToTest.getDay() <= 6 &&
            dateToTest.getMonth() == firstDay.getMonth()
        ) {
            days.push(new Date(dateToTest));
            dateToTest.setDate(dateToTest.getDate()   1);
        }

        return days;
    };

    // The first day of the month
    const firstDay = new Date(current.getFullYear(), current.getMonth());
    let dateToTest = new Date(firstDay);
    do {
        weeks.push(getWeek(dateToTest));
        dateToTest = new Date(lastItem(lastItem(weeks)));
        dateToTest.setDate(dateToTest.getDate()   1);
    } while (dateToTest.getMonth() == firstDay.getMonth());

    // Filter to half of the month
    // Get the week of the given date
    let currentWeek = 0;
    weekLoop: for (let i = 0; i < weeks.length; i  ) {
        const week = weeks[i];
        for (const day of week) {
            if (day == current) {
                currentWeek = i;
                break weekLoop;
            }
        }
    }

    /** @type {[[Date]]} */
    let weeksInHalf = [];

    const numOfWeeksInFirstHalf = Math.ceil(weeks.length / 2),
        numOfWeeksInSecondHalf = weeks.length - numOfWeeksInFirstHalf;

    for (
        let i = 0;
        i <
        (currentWeek < numOfWeeksInFirstHalf
            ? numOfWeeksInFirstHalf
            : numOfWeeksInSecondHalf);
        i  
    ) {
        weeksInHalf.push(weeks[i]);
    }

    // Filter out weekends
    // Format dates
    return weeksInHalf
        .flat()
        .filter(day => day.getDay() > 0 && day.getDay() < 6)
        .map(
            day => `${day.getFullYear()}-${day.getMonth()   1}-${day.getDate()}`
        );
};

// Tests
for (let i = 0; i < 12; i  ) {
    const weekdays = getWeekdays(new Date(2022, i));
    weekdays.forEach(dateString => {
        const [year, month, day] = dateString.split("-");
        const date = new Date(year, month - 1, day);
        if (date.getDay() == 0 || date.getDay() == 6)
            throw new Error("Invalid day: (day)");
        else console.log(dateString)
    });
}

  • Related