Calculate previous working day excluding weekends and federal holidays in JavaScript

后端 未结 2 451
暖寄归人
暖寄归人 2021-01-27 07:02

I am writing a function which will provide me previous working day for any given date. Working day means it is a weekday and there\'s no federal holiday on that day.

My

相关标签:
2条回答
  • 2021-01-27 07:25

    When you are checking for holidays array you are checking full date instead of the date part.

    function check_previous_business_date(date, timezone) {
          const startDate = new Date(luxon.DateTime.fromISO(date).setZone(timezone));
          const todayTimeStamp = +new Date(startDate); // Unix timestamp in milliseconds
          const oneDayTimeStamp = 1000 * 60 * 60 * 24; // Milliseconds in a day
          const diff = todayTimeStamp - oneDayTimeStamp;
          const yesterdayDate = new Date(diff);
          const yesterdayString = yesterdayDate.getFullYear()
             + '-' + (yesterdayDate.getMonth() + 1) + '-' + yesterdayDate.getDate();
          for (startDate.setDate(startDate.getDate() - 1);
            !startDate.getDay() || startDate.getDay() === 6 ||
            federalHolidays.includes(startDate.toISOString().split('T')[0]) ||
            federalHolidays.includes(yesterdayString);
            startDate.setDate(startDate.getDate() - 1)
          ) { 
          }
    
          return startDate.toISOString().split('T')[0];
        }
    const federalHolidays= [
      '2019-05-27',
      '2019-09-02',
      '2019-10-14',
      '2019-11-11'
    ];
    console.log('Prev. day of 2019-05-28 is ',check_previous_business_date('2019-05-28T07:00:00.000Z', 'America/New_York'));
    console.log('Prev. day of 2019-06-20 is ',check_previous_business_date('2019-06-20T07:00:00.000Z', 'America/New_York'));
    <script src="https://cdn.jsdelivr.net/npm/luxon@1.21.1/build/global/luxon.min.js"></script>

    0 讨论(0)
  • 2021-01-27 07:27

    You are not using Luxon to its full potential. You should leave the date as a Luxon object, do all the operations on it using Luxon's methods, and then convert the date into a string.

    To do that, I defined a helper function prevBusinessDayHelper that takes a Luxon datetime and returns a date time representing the previous business day. It operates entirely in terms of Luxon datetimes, which makes it easy. Then in the outer function, I convert to and from Luxon datetimes.

    const DateTime = luxon.DateTime;
    
    // use a Set to make lookups cheaper
    const federalHolidays = new Set([
      '2019-05-27', // <-- you were missing the 0 here in yours
      '2019-09-02',
      // snip
    ]);
    
    // recursion is good here because it's very shallow
    const prevBusinessDayHelper = dt => {
    
      // use luxon's tools!
      const yest = dt.minus({ days: 1 });
    
      if (yest.weekday == 6 || yest.weekday == 7 || federalHolidays.has(yest.toISODate()))
        return prevBusinessDayHelper(yest);
    
      return yest;
    };
    
    const prevBusinessDay = (isoString, zone) => {
      const dt = DateTime.fromISO(isoString).setZone(zone);
      return prevBusinessDayHelper(dt).toISODate();
    };
    
    console.log(prevBusinessDay("2019-05-28T07:00:00.000Z", "America/New_York"));
    <script src="https://cdn.jsdelivr.net/npm/luxon@1.21.1/build/global/luxon.min.js"></script>

    0 讨论(0)
提交回复
热议问题