简体   繁体   中英

Check if period of date, is overlapping any of the given period in the array

I have a module for sales-person, where they can add their own managers. These will be displayed in ag-grid on UI. To add managers I need to select the manager, period start date, and period end date for a given manager. But simultaneously I also need to check the period of each manager, that any of the manager's dates should not overlap each other, based on it there Status is being decided. There can be N number of managers to a salesperson, but there should be only one Active manager to each sales-person at a time.

I am currently facing an issue while comparing the dates of the current manager to each of the given managers in the array.

I decide the status based on the following code:

decideStatus(): string {
    let status = '';
    let currentDate = new Date();
    let fromDate = this.salesPersonForm.value.StartDate;
    let tillDate = this.salesPersonForm.value.EndDate;

    if(fromDate <= currentDate && (tillDate > currentDate || tillDate == null)) {
      return status = 'Active'
    } else if(fromDate > currentDate) {
      return status = 'Onhold'
    } else if(tillDate < currentDate) {
      return status = 'Inactive'
    }
  }

I have the following piece of code for the adding the manager to the grid.

addManagers(){
    if(this.salesPersonForm.value.SalesPerson) {
      if(this.salesPersonForm.value.StartDate) {
        if(this.salesPersonForm.value.EndDate == null || (this.salesPersonForm.value.EndDate > this.salesPersonForm.value.StartDate)) {
          let loggedInUser = userName;
          let manager = {
            Name: someName
            FromDate: this.salesPersonForm.value.StartDate 
            TillDate: this.salesPersonForm.value.EndDate 
            CreatedAt: new Date()
            CreatedBy: loggedInUser,
            Status: this.decideStatus()
          }
          this.managers.push(manager)
        } else {
          return;
        }
      } else {
        return;
      }
    } else {
      return
    }
    this.clear();
    setTimeout(() => {
      this.agGridReference.assignData(this.managers)
    }, 200);
  }

Idle UseCase: M1 - 01/01/2020 to 31/06/2020 - InActive M2 - 01/08/2020 to 31/12/2021 - InActive M3 - 01/01/2022 to somefuturevalue - Active

If dates are in the future than the current date, it will be considered as on hold.

InValid case: M1 - 01/01/2020 to 31/06/2020 - InActive M2 - 01/05/2020 to 28/02/2021 - InActive M3 - 01/01/2021 to 30/05/2021 - InActive

Ok, so you're going to push new manager into managers array only if new manager's interval is not overlapping with any existing manager's interval. Thus the check needs to be made before your this.managers.push(manager) line, something like this:

  • replacing this.managers.push(manager) with: this.compareDates(manager);

  • adding these two methods:

compareDates(newM) {
    let overlaps = 0;
    this.managers.forEach(m => {
      if (
        // first case:
        // saved manager starts before FromDate
        // and finishes after FromDate
        // of new manager:
        (this.prepareDate(m.FromDate) <= this.prepareDate(newM.FromDate) &&
          this.prepareDate(m.TillDate) >= this.prepareDate(newM.FromDate)) ||
        // second case:
        // saved manager starts after FromDate
        // and before the TillDate
        // of new manager:
        (this.prepareDate(m.FromDate) >= this.prepareDate(newM.FromDate) &&
          this.prepareDate(m.FromDate) <= this.prepareDate(newM.TillDate))
      ) {
        overlaps++;
      }
    });
    if (overlaps == 0) {
      // no overlaps, so push this new manager and do whatever else needs to be done
      this.managers.push(newM);
      console.log('Welcome, new manager!');
    } 
    else {
      // there is at least 1 overlap, so do something else
      // like: return with error message  
      console.log("This manager's interval overlaps with interval(s) of " 
      + overlaps +' other manager(s)!'
      );
    }
  }

And the helper method to return timestamp of each date in the previous method:

prepareDate(date) {
    let parts = date.split('/');
    return Date.parse(parts[2] + '/' + parts[1] + '/' + parts[0]);
}

To see it in action: https://stackblitz.com/edit/angular-ivy-j9ldef

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM