4

Here is my days list

days_list: any[] = [
    {
      id: 0,
      value: 'Monday'
    },
    {
      id: 1,
      value: 'Tuesday'
    }, {
      id: 2,
      value: 'Wednesday'
    }, {
      id: 3,
      value: 'Thursday'
    }, {
      id: 4,
      value: 'Friday'
    }, {
      id: 5,
      value: 'Saturday'
    },
    {
      id: 6,
      value: 'Sunday'
    },
  ]

Here is my Business Hours

business_hours = { day_to: 2, time_to: "23:00", day_from: 5, time_from: "08:00" }

I'm using UTC date format I want to know if the day from days_list exist according to day_from and day_to

For example here day_from is 5 which is Saturday and day_to is 2 Wednesday so the required array is: ["Saturday", "Sunday", "Monday". "Tuesday". "Wednesday"] and the same for time if the current time exists in time_from and time_to,

My code is:

   const activationDate = new Date();

    const d_date = activationDate.getUTCDay() - 1;
    console.log(d_date);

    const B_from = this.getMin(this.business_hours.time_from);

    const B_To = this.getMin(this.business_hours.time_to);


    const min = activationDate.getUTCMinutes();
    console.log(min)
    const naan = activationDate.getUTCHours();
    console.log(naan)
    const utcTime = this.getUtcMin(naan, min);



    for(let j = 0; j < this.business_hours.day_to; j++) {
    for (let i = this.business_hours.day_from; i < this.days_list.length; i++) {
     
      console.log(this.days_list[i]);

      if (this.days_list[i].id === d_date) {
        this.is_open = true;
        console.log(this.days_list[i].value);
      }
     }
    }

it's not giving the required results.

Randy Casburn
  • 13,840
  • 1
  • 16
  • 31
Dev Deem
  • 43
  • 3
  • Possible duplicate of [How to access array in circular manner in JavaScript](https://stackoverflow.com/questions/17483149/how-to-access-array-in-circular-manner-in-javascript) – jcalz Dec 22 '20 at 02:01

3 Answers3

2

My understanding is you'd like to treat your array as circular, and then slice it according to a "from" and "to" index, where both the "from" and "to" indexes are treated as inclusive.

Let's assume you have an array of strings like this:

console.log(dayArray);
// ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] 

(which you can turn your structure into easily enough like:

const dayArray = days_list.reduce<string[]>((a, d) => (a[d.id] = d.value, a), []);

)

Then you can write a circular array slice with inclusive endpoints function in any number of ways. Here's one:

function circularArraySlice<T>(arr: T[], fromIndex: number, toIndex: number) {
  return arr.map((_, i, a) => a[(i + fromIndex) % a.length]).
    slice(0, ((arr.length + toIndex - fromIndex) % arr.length) + 1);
}

Essentially we're walking off the end of the array and back onto the beginning using modular arithmetic as (almost) implemented by the JS remainder operator (%). Let's see if it works:

console.log(circularArraySlice(dayArray, 5, 2));
// ["Saturday", "Sunday", "Monday", "Tuesday", "Wednesday"] 

console.log(circularArraySlice(dayArray, 2, 5));
// ["Wednesday", "Thursday", "Friday", "Saturday"]

This is, I think, what you want. There may well be edge cases so be careful.

Playground link to code

jcalz
  • 264,269
  • 27
  • 359
  • 360
1

To help answer questions like this, I'd recommend listing a couple of test cases and both provide expected values and the values you're actually seeing.

But I can see a couple of things which may cause problems in the code:

  • The calculation of d_date is going to return -1 for Sunday, not 6 (like days_list is expecting)
  • The outer loop (the one setting j) isn't really adding a lot here, because j isn't used inside the loop. Therefore, each iteration of the loop is going to have the same effect.
  • The inner loop (the one setting i) is only looking for days which appear after day_from in your days_list array. However, as per you example, days from the start of days_list may also match if the day_from value is greater than day_to.
lucas
  • 1,910
  • 2
  • 21
  • 25
1

Based on Randy Casburn's (now-deleted) answer, it's possible to solve this using javascript's filter method. However, you need to be extra careful to handle separate cases for when to_date is before from_date and vice-versa.

For example:

const days_list = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];

function getDays(business_hours) {
  const days = days_list.filter((_, id) => {
      if (business_hours.day_from <= business_hours.day_to) {
        return (id >= business_hours.day_from && id <= business_hours.day_to);
      } else {
        return (id <= business_hours.day_to || id >= business_hours.day_from);
      }
  })
  console.log(business_hours, days);
  return days;
}
getDays({ day_from: 2, time_from: "23:00", day_to: 5, time_to: "08:00"});
getDays({ day_to: 2, time_to: "23:00", day_from: 5, time_from: "08:00"});
getDays({ day_from: 3, time_from: "23:00", day_to: 3, time_to: "08:00"});
lucas
  • 1,910
  • 2
  • 21
  • 25