Search code examples
javascriptdatedayjs

Recurring date using dayjs with dayrs-recur


I’m willing to create a recurring date based on "nth weekday of month" Here is my solution work when I select current Date

let dates = {};
 const currentDate = dayjs();
 const recurrence = currentDate
   .recur(dayjs().add(4, "month"))
   .every("Wednesday")
   .daysOfWeek()
   .every(currentDate.monthWeekByDay())
   .weeksOfMonthByDay();
 recurrence.all().forEach((date) => {
   dates[date.format("YYYY-MM-DD")] = { selected: true, };
 });
// dates = ["2022-09-21","2022-10-19","2022-11-16","2022-12-21","2023-01-18"]

but if put last day of this month which is 30

 let dates = {};

  const lastDayofMonth = dayjs().endOf("month");
  const recurrence = lastDayofMonth
    .recur(dayjs().add(4, "month"))
    .every("Friday")
    .daysOfWeek()
    .every(lastDayofMonth.monthWeekByDay())
    .weeksOfMonthByDay();

I was expecting to get

["2022-09-30","2022-10-28","2022-11-25","2022-12-30"..]

instead of

["2022-09-30","2022-12-30"]

Here is demo

Am I missing something ? Thanks in advance


Solution

  • It possible to create a recurring date based on "nth weekday of month" with dayjs and dayjs-recur as all months as different number of weeks

    But there are some challenges:

    • A month has 4 weeks on average (some months have few or no days for fifth week)
    • Due to this there may be cases where there is no fifth week or the fifth week doesn't have the nth weekday

    To resolve this

    • If you are getting an nth weekday of month where the week is the last week of the month (could be 4th/5th week)
    • Get both the nth weekday of month for the last week (5th) and the fourth (4th) week
    • From the list of dates returned filter if dates for a month occur multiple times and select the latest/greatest one
    • The filtered result should have the nth weekday of month where the week is the last week of the month

    Demo

    Below is a link to a working demo forked from @Achraf's demo on code sandbox

    Demo Link

    Code Example

      const lastDayofMonth = dayjs().endOf("month");
    
      const recurrence = lastDayofMonth
        .recur(dayjs().add(4, "month"))
        .every("Friday")
        .daysOfWeek()
        .every([3, 4])
        .weeksOfMonthByDay();
    
      // filter recurrence
      const months = {};
      recurrence.all().forEach((date) => {
        months[date.month()] = date;
      })
    
      // get filtered dates
      const filteredDates = Object.values(months);
    
      // formot date into dates object
      filteredDates.forEach((date) => {
        dates[date.format("YYYY-MM-DD")] = { selected: true, color: "#2FB0ED" };
      });
    
      console.log("dates", dates);
      // ["2022-09-30","2022-10-28","2022-11-25","2022-12-30"..]