Calculate the intersections of opening hours

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
5
down vote

favorite
1












I have a solution but it feels bloated and unclean. How can I clean it up? The second for loop especially does not feel right.



I'm trying to calculate the opening hours but where we only use the highest opening time and the lowest closing time in a time-block. I will show you an example to clarify it.



If we have two time-blocks with



10:00-12:00 and 10:30-12:30


The result for the opening hour is going to be



10:30-12:00


Now imagine we have an array for a specific day:



[

"opens": "10:00",
"closes": "12:00",
"weekday": 5
,

"opens": "16:00",
"closes": "19:30",
"weekday": 5
,

"opens": "11:00",
"closes": "12:30",
"weekday": 5
,

"opens": "17:00",
"closes": "18:30",
"weekday": 5

]


Our opening hour should be for this day:



[

"opens": "11:00",
"closes": "12:00"
,

"opens": "17:00",
"closes": "18:30"

]


Now to my approach:



First I'm going to through the whole opening hour array for a specific day:



this.filteredTimes.forEach((time, index, array) => ...);


Inside the for loop, I'm saving the opens and closes time in MomentJS:



let opens = this.momentTime(time.opens); //saving it to moment
let closes = this.momentTime(time.closes); //moment(time, 'HH:mm')


After that, I'm again going through the whole array in another for loop:



for(let i = 0; i < array.length; i++)... //array === this.filteredTimes


Inside the loop, I'm saving the opens and closes times for each time block again, but now I'm comparing it to the opens and closes time from the first for loop.



let arrayOpens = this.momentTime(array[i].opens);
let arrayCloses = this.momentTime(array[i].closes);

if(arrayOpens.isBetween(opens, closes))
opens = arrayOpens.isAfter(opens) ? arrayOpens : opens;



If the arrayOpens is between the saved time block, we can save a new opens time if our condition is true.



After that, we are going to save the new opens and closes time and we try to avoid duplication:



let hour = 
opens: opens.format('HH:mm'),
closes: closes.format('HH:mm')
;

if(! openingHour.find(element => element.opens == hour.opens && element.closes == hour.closes))
openingHour.push(hour);



The whole code is here to test (or on JsFiddle):






moment().format();


let filteredTimes = [

"opens": "10:00",
"closes": "12:00",
"weekday": 5
,

"opens": "16:00",
"closes": "19:30",
"weekday": 5
,

"opens": "11:00",
"closes": "12:30",
"weekday": 5
,

"opens": "17:00",
"closes": "18:30",
"weekday": 5

];

let openingHour = ;

calculate();


function calculate()

filteredTimes.forEach((time, index, array) =>
let opens = momentTime(time.opens);
let closes = momentTime(time.closes);

for(let i = 0; i < array.length; i++)
let arrayOpens = momentTime(array[i].opens);
let arrayCloses = momentTime(array[i].closes);

if(arrayOpens.isBetween(opens, closes))
opens = arrayOpens.isAfter(opens) ? arrayOpens : opens;

if(arrayCloses.isBetween(opens, closes))
closes = arrayCloses.isBefore(closes) ? arrayCloses : closes;



let hour =
opens: opens.format('HH:mm'),
closes: closes.format('HH:mm')
;

if(! openingHour.find(element => element.opens == hour.opens && element.closes == hour.closes))

openingHour.push(hour);


);

console.log(openingHour);
return openingHour;


function momentTime(time)
return moment(time, 'HH:mm');

<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>









share|improve this question





















  • Have you considered sorting the opening/closing times, possibly using something like h*60+m as the sort value?
    – Barry Carter
    Jun 20 at 17:09










  • I'm misunderstanding something here. If two time blocks don't overlap, shouldn't the opening/closing become null, since the earliest closes time is later than the latest opens time? Or is that a special case?
    – Barry Carter
    Jun 20 at 17:19










  • @BarryCarter sorry I could not answer straight away. I try to explain how these opening hours even exists. Imagine you are able to sell something. Every time you sell something, I need to know what your preferred pickup times are (it's the same as opening hours). If you sell another thing, you need to write down another pickup times. So that is why I need to try to find the difference between those times. (And it's just a reference point, the buyer can chat with him and of course choose to come to another time).
    – Shadrix
    Jun 21 at 9:17










  • @BarryCarter and because the user has different "opening hours" in a day. (In the morning the user has got time until 9, after that he is not at home, but at 18:00 he is ready again). And the opening/closing times are sorted with array.sort()
    – Shadrix
    Jun 21 at 9:19










  • You might want to condense your question into 1) the context/use case/ scenario 2) your code. You do not need to explain how you're doing it, the code pretty much does that for you.
    – Joseph
    Jun 21 at 20:58
















up vote
5
down vote

favorite
1












I have a solution but it feels bloated and unclean. How can I clean it up? The second for loop especially does not feel right.



I'm trying to calculate the opening hours but where we only use the highest opening time and the lowest closing time in a time-block. I will show you an example to clarify it.



If we have two time-blocks with



10:00-12:00 and 10:30-12:30


The result for the opening hour is going to be



10:30-12:00


Now imagine we have an array for a specific day:



[

"opens": "10:00",
"closes": "12:00",
"weekday": 5
,

"opens": "16:00",
"closes": "19:30",
"weekday": 5
,

"opens": "11:00",
"closes": "12:30",
"weekday": 5
,

"opens": "17:00",
"closes": "18:30",
"weekday": 5

]


Our opening hour should be for this day:



[

"opens": "11:00",
"closes": "12:00"
,

"opens": "17:00",
"closes": "18:30"

]


Now to my approach:



First I'm going to through the whole opening hour array for a specific day:



this.filteredTimes.forEach((time, index, array) => ...);


Inside the for loop, I'm saving the opens and closes time in MomentJS:



let opens = this.momentTime(time.opens); //saving it to moment
let closes = this.momentTime(time.closes); //moment(time, 'HH:mm')


After that, I'm again going through the whole array in another for loop:



for(let i = 0; i < array.length; i++)... //array === this.filteredTimes


Inside the loop, I'm saving the opens and closes times for each time block again, but now I'm comparing it to the opens and closes time from the first for loop.



let arrayOpens = this.momentTime(array[i].opens);
let arrayCloses = this.momentTime(array[i].closes);

if(arrayOpens.isBetween(opens, closes))
opens = arrayOpens.isAfter(opens) ? arrayOpens : opens;



If the arrayOpens is between the saved time block, we can save a new opens time if our condition is true.



After that, we are going to save the new opens and closes time and we try to avoid duplication:



let hour = 
opens: opens.format('HH:mm'),
closes: closes.format('HH:mm')
;

if(! openingHour.find(element => element.opens == hour.opens && element.closes == hour.closes))
openingHour.push(hour);



The whole code is here to test (or on JsFiddle):






moment().format();


let filteredTimes = [

"opens": "10:00",
"closes": "12:00",
"weekday": 5
,

"opens": "16:00",
"closes": "19:30",
"weekday": 5
,

"opens": "11:00",
"closes": "12:30",
"weekday": 5
,

"opens": "17:00",
"closes": "18:30",
"weekday": 5

];

let openingHour = ;

calculate();


function calculate()

filteredTimes.forEach((time, index, array) =>
let opens = momentTime(time.opens);
let closes = momentTime(time.closes);

for(let i = 0; i < array.length; i++)
let arrayOpens = momentTime(array[i].opens);
let arrayCloses = momentTime(array[i].closes);

if(arrayOpens.isBetween(opens, closes))
opens = arrayOpens.isAfter(opens) ? arrayOpens : opens;

if(arrayCloses.isBetween(opens, closes))
closes = arrayCloses.isBefore(closes) ? arrayCloses : closes;



let hour =
opens: opens.format('HH:mm'),
closes: closes.format('HH:mm')
;

if(! openingHour.find(element => element.opens == hour.opens && element.closes == hour.closes))

openingHour.push(hour);


);

console.log(openingHour);
return openingHour;


function momentTime(time)
return moment(time, 'HH:mm');

<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>









share|improve this question





















  • Have you considered sorting the opening/closing times, possibly using something like h*60+m as the sort value?
    – Barry Carter
    Jun 20 at 17:09










  • I'm misunderstanding something here. If two time blocks don't overlap, shouldn't the opening/closing become null, since the earliest closes time is later than the latest opens time? Or is that a special case?
    – Barry Carter
    Jun 20 at 17:19










  • @BarryCarter sorry I could not answer straight away. I try to explain how these opening hours even exists. Imagine you are able to sell something. Every time you sell something, I need to know what your preferred pickup times are (it's the same as opening hours). If you sell another thing, you need to write down another pickup times. So that is why I need to try to find the difference between those times. (And it's just a reference point, the buyer can chat with him and of course choose to come to another time).
    – Shadrix
    Jun 21 at 9:17










  • @BarryCarter and because the user has different "opening hours" in a day. (In the morning the user has got time until 9, after that he is not at home, but at 18:00 he is ready again). And the opening/closing times are sorted with array.sort()
    – Shadrix
    Jun 21 at 9:19










  • You might want to condense your question into 1) the context/use case/ scenario 2) your code. You do not need to explain how you're doing it, the code pretty much does that for you.
    – Joseph
    Jun 21 at 20:58












up vote
5
down vote

favorite
1









up vote
5
down vote

favorite
1






1





I have a solution but it feels bloated and unclean. How can I clean it up? The second for loop especially does not feel right.



I'm trying to calculate the opening hours but where we only use the highest opening time and the lowest closing time in a time-block. I will show you an example to clarify it.



If we have two time-blocks with



10:00-12:00 and 10:30-12:30


The result for the opening hour is going to be



10:30-12:00


Now imagine we have an array for a specific day:



[

"opens": "10:00",
"closes": "12:00",
"weekday": 5
,

"opens": "16:00",
"closes": "19:30",
"weekday": 5
,

"opens": "11:00",
"closes": "12:30",
"weekday": 5
,

"opens": "17:00",
"closes": "18:30",
"weekday": 5

]


Our opening hour should be for this day:



[

"opens": "11:00",
"closes": "12:00"
,

"opens": "17:00",
"closes": "18:30"

]


Now to my approach:



First I'm going to through the whole opening hour array for a specific day:



this.filteredTimes.forEach((time, index, array) => ...);


Inside the for loop, I'm saving the opens and closes time in MomentJS:



let opens = this.momentTime(time.opens); //saving it to moment
let closes = this.momentTime(time.closes); //moment(time, 'HH:mm')


After that, I'm again going through the whole array in another for loop:



for(let i = 0; i < array.length; i++)... //array === this.filteredTimes


Inside the loop, I'm saving the opens and closes times for each time block again, but now I'm comparing it to the opens and closes time from the first for loop.



let arrayOpens = this.momentTime(array[i].opens);
let arrayCloses = this.momentTime(array[i].closes);

if(arrayOpens.isBetween(opens, closes))
opens = arrayOpens.isAfter(opens) ? arrayOpens : opens;



If the arrayOpens is between the saved time block, we can save a new opens time if our condition is true.



After that, we are going to save the new opens and closes time and we try to avoid duplication:



let hour = 
opens: opens.format('HH:mm'),
closes: closes.format('HH:mm')
;

if(! openingHour.find(element => element.opens == hour.opens && element.closes == hour.closes))
openingHour.push(hour);



The whole code is here to test (or on JsFiddle):






moment().format();


let filteredTimes = [

"opens": "10:00",
"closes": "12:00",
"weekday": 5
,

"opens": "16:00",
"closes": "19:30",
"weekday": 5
,

"opens": "11:00",
"closes": "12:30",
"weekday": 5
,

"opens": "17:00",
"closes": "18:30",
"weekday": 5

];

let openingHour = ;

calculate();


function calculate()

filteredTimes.forEach((time, index, array) =>
let opens = momentTime(time.opens);
let closes = momentTime(time.closes);

for(let i = 0; i < array.length; i++)
let arrayOpens = momentTime(array[i].opens);
let arrayCloses = momentTime(array[i].closes);

if(arrayOpens.isBetween(opens, closes))
opens = arrayOpens.isAfter(opens) ? arrayOpens : opens;

if(arrayCloses.isBetween(opens, closes))
closes = arrayCloses.isBefore(closes) ? arrayCloses : closes;



let hour =
opens: opens.format('HH:mm'),
closes: closes.format('HH:mm')
;

if(! openingHour.find(element => element.opens == hour.opens && element.closes == hour.closes))

openingHour.push(hour);


);

console.log(openingHour);
return openingHour;


function momentTime(time)
return moment(time, 'HH:mm');

<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>









share|improve this question













I have a solution but it feels bloated and unclean. How can I clean it up? The second for loop especially does not feel right.



I'm trying to calculate the opening hours but where we only use the highest opening time and the lowest closing time in a time-block. I will show you an example to clarify it.



If we have two time-blocks with



10:00-12:00 and 10:30-12:30


The result for the opening hour is going to be



10:30-12:00


Now imagine we have an array for a specific day:



[

"opens": "10:00",
"closes": "12:00",
"weekday": 5
,

"opens": "16:00",
"closes": "19:30",
"weekday": 5
,

"opens": "11:00",
"closes": "12:30",
"weekday": 5
,

"opens": "17:00",
"closes": "18:30",
"weekday": 5

]


Our opening hour should be for this day:



[

"opens": "11:00",
"closes": "12:00"
,

"opens": "17:00",
"closes": "18:30"

]


Now to my approach:



First I'm going to through the whole opening hour array for a specific day:



this.filteredTimes.forEach((time, index, array) => ...);


Inside the for loop, I'm saving the opens and closes time in MomentJS:



let opens = this.momentTime(time.opens); //saving it to moment
let closes = this.momentTime(time.closes); //moment(time, 'HH:mm')


After that, I'm again going through the whole array in another for loop:



for(let i = 0; i < array.length; i++)... //array === this.filteredTimes


Inside the loop, I'm saving the opens and closes times for each time block again, but now I'm comparing it to the opens and closes time from the first for loop.



let arrayOpens = this.momentTime(array[i].opens);
let arrayCloses = this.momentTime(array[i].closes);

if(arrayOpens.isBetween(opens, closes))
opens = arrayOpens.isAfter(opens) ? arrayOpens : opens;



If the arrayOpens is between the saved time block, we can save a new opens time if our condition is true.



After that, we are going to save the new opens and closes time and we try to avoid duplication:



let hour = 
opens: opens.format('HH:mm'),
closes: closes.format('HH:mm')
;

if(! openingHour.find(element => element.opens == hour.opens && element.closes == hour.closes))
openingHour.push(hour);



The whole code is here to test (or on JsFiddle):






moment().format();


let filteredTimes = [

"opens": "10:00",
"closes": "12:00",
"weekday": 5
,

"opens": "16:00",
"closes": "19:30",
"weekday": 5
,

"opens": "11:00",
"closes": "12:30",
"weekday": 5
,

"opens": "17:00",
"closes": "18:30",
"weekday": 5

];

let openingHour = ;

calculate();


function calculate()

filteredTimes.forEach((time, index, array) =>
let opens = momentTime(time.opens);
let closes = momentTime(time.closes);

for(let i = 0; i < array.length; i++)
let arrayOpens = momentTime(array[i].opens);
let arrayCloses = momentTime(array[i].closes);

if(arrayOpens.isBetween(opens, closes))
opens = arrayOpens.isAfter(opens) ? arrayOpens : opens;

if(arrayCloses.isBetween(opens, closes))
closes = arrayCloses.isBefore(closes) ? arrayCloses : closes;



let hour =
opens: opens.format('HH:mm'),
closes: closes.format('HH:mm')
;

if(! openingHour.find(element => element.opens == hour.opens && element.closes == hour.closes))

openingHour.push(hour);


);

console.log(openingHour);
return openingHour;


function momentTime(time)
return moment(time, 'HH:mm');

<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>








moment().format();


let filteredTimes = [

"opens": "10:00",
"closes": "12:00",
"weekday": 5
,

"opens": "16:00",
"closes": "19:30",
"weekday": 5
,

"opens": "11:00",
"closes": "12:30",
"weekday": 5
,

"opens": "17:00",
"closes": "18:30",
"weekday": 5

];

let openingHour = ;

calculate();


function calculate()

filteredTimes.forEach((time, index, array) =>
let opens = momentTime(time.opens);
let closes = momentTime(time.closes);

for(let i = 0; i < array.length; i++)
let arrayOpens = momentTime(array[i].opens);
let arrayCloses = momentTime(array[i].closes);

if(arrayOpens.isBetween(opens, closes))
opens = arrayOpens.isAfter(opens) ? arrayOpens : opens;

if(arrayCloses.isBetween(opens, closes))
closes = arrayCloses.isBefore(closes) ? arrayCloses : closes;



let hour =
opens: opens.format('HH:mm'),
closes: closes.format('HH:mm')
;

if(! openingHour.find(element => element.opens == hour.opens && element.closes == hour.closes))

openingHour.push(hour);


);

console.log(openingHour);
return openingHour;


function momentTime(time)
return moment(time, 'HH:mm');

<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>





moment().format();


let filteredTimes = [

"opens": "10:00",
"closes": "12:00",
"weekday": 5
,

"opens": "16:00",
"closes": "19:30",
"weekday": 5
,

"opens": "11:00",
"closes": "12:30",
"weekday": 5
,

"opens": "17:00",
"closes": "18:30",
"weekday": 5

];

let openingHour = ;

calculate();


function calculate()

filteredTimes.forEach((time, index, array) =>
let opens = momentTime(time.opens);
let closes = momentTime(time.closes);

for(let i = 0; i < array.length; i++)
let arrayOpens = momentTime(array[i].opens);
let arrayCloses = momentTime(array[i].closes);

if(arrayOpens.isBetween(opens, closes))
opens = arrayOpens.isAfter(opens) ? arrayOpens : opens;

if(arrayCloses.isBetween(opens, closes))
closes = arrayCloses.isBefore(closes) ? arrayCloses : closes;



let hour =
opens: opens.format('HH:mm'),
closes: closes.format('HH:mm')
;

if(! openingHour.find(element => element.opens == hour.opens && element.closes == hour.closes))

openingHour.push(hour);


);

console.log(openingHour);
return openingHour;


function momentTime(time)
return moment(time, 'HH:mm');

<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>








share|improve this question












share|improve this question




share|improve this question








edited Jun 23 at 2:25









Jamal♦

30.1k11114225




30.1k11114225









asked Jun 20 at 13:33









Shadrix

283




283











  • Have you considered sorting the opening/closing times, possibly using something like h*60+m as the sort value?
    – Barry Carter
    Jun 20 at 17:09










  • I'm misunderstanding something here. If two time blocks don't overlap, shouldn't the opening/closing become null, since the earliest closes time is later than the latest opens time? Or is that a special case?
    – Barry Carter
    Jun 20 at 17:19










  • @BarryCarter sorry I could not answer straight away. I try to explain how these opening hours even exists. Imagine you are able to sell something. Every time you sell something, I need to know what your preferred pickup times are (it's the same as opening hours). If you sell another thing, you need to write down another pickup times. So that is why I need to try to find the difference between those times. (And it's just a reference point, the buyer can chat with him and of course choose to come to another time).
    – Shadrix
    Jun 21 at 9:17










  • @BarryCarter and because the user has different "opening hours" in a day. (In the morning the user has got time until 9, after that he is not at home, but at 18:00 he is ready again). And the opening/closing times are sorted with array.sort()
    – Shadrix
    Jun 21 at 9:19










  • You might want to condense your question into 1) the context/use case/ scenario 2) your code. You do not need to explain how you're doing it, the code pretty much does that for you.
    – Joseph
    Jun 21 at 20:58
















  • Have you considered sorting the opening/closing times, possibly using something like h*60+m as the sort value?
    – Barry Carter
    Jun 20 at 17:09










  • I'm misunderstanding something here. If two time blocks don't overlap, shouldn't the opening/closing become null, since the earliest closes time is later than the latest opens time? Or is that a special case?
    – Barry Carter
    Jun 20 at 17:19










  • @BarryCarter sorry I could not answer straight away. I try to explain how these opening hours even exists. Imagine you are able to sell something. Every time you sell something, I need to know what your preferred pickup times are (it's the same as opening hours). If you sell another thing, you need to write down another pickup times. So that is why I need to try to find the difference between those times. (And it's just a reference point, the buyer can chat with him and of course choose to come to another time).
    – Shadrix
    Jun 21 at 9:17










  • @BarryCarter and because the user has different "opening hours" in a day. (In the morning the user has got time until 9, after that he is not at home, but at 18:00 he is ready again). And the opening/closing times are sorted with array.sort()
    – Shadrix
    Jun 21 at 9:19










  • You might want to condense your question into 1) the context/use case/ scenario 2) your code. You do not need to explain how you're doing it, the code pretty much does that for you.
    – Joseph
    Jun 21 at 20:58















Have you considered sorting the opening/closing times, possibly using something like h*60+m as the sort value?
– Barry Carter
Jun 20 at 17:09




Have you considered sorting the opening/closing times, possibly using something like h*60+m as the sort value?
– Barry Carter
Jun 20 at 17:09












I'm misunderstanding something here. If two time blocks don't overlap, shouldn't the opening/closing become null, since the earliest closes time is later than the latest opens time? Or is that a special case?
– Barry Carter
Jun 20 at 17:19




I'm misunderstanding something here. If two time blocks don't overlap, shouldn't the opening/closing become null, since the earliest closes time is later than the latest opens time? Or is that a special case?
– Barry Carter
Jun 20 at 17:19












@BarryCarter sorry I could not answer straight away. I try to explain how these opening hours even exists. Imagine you are able to sell something. Every time you sell something, I need to know what your preferred pickup times are (it's the same as opening hours). If you sell another thing, you need to write down another pickup times. So that is why I need to try to find the difference between those times. (And it's just a reference point, the buyer can chat with him and of course choose to come to another time).
– Shadrix
Jun 21 at 9:17




@BarryCarter sorry I could not answer straight away. I try to explain how these opening hours even exists. Imagine you are able to sell something. Every time you sell something, I need to know what your preferred pickup times are (it's the same as opening hours). If you sell another thing, you need to write down another pickup times. So that is why I need to try to find the difference between those times. (And it's just a reference point, the buyer can chat with him and of course choose to come to another time).
– Shadrix
Jun 21 at 9:17












@BarryCarter and because the user has different "opening hours" in a day. (In the morning the user has got time until 9, after that he is not at home, but at 18:00 he is ready again). And the opening/closing times are sorted with array.sort()
– Shadrix
Jun 21 at 9:19




@BarryCarter and because the user has different "opening hours" in a day. (In the morning the user has got time until 9, after that he is not at home, but at 18:00 he is ready again). And the opening/closing times are sorted with array.sort()
– Shadrix
Jun 21 at 9:19












You might want to condense your question into 1) the context/use case/ scenario 2) your code. You do not need to explain how you're doing it, the code pretty much does that for you.
– Joseph
Jun 21 at 20:58




You might want to condense your question into 1) the context/use case/ scenario 2) your code. You do not need to explain how you're doing it, the code pretty much does that for you.
– Joseph
Jun 21 at 20:58










1 Answer
1






active

oldest

votes

















up vote
2
down vote



accepted










  • calculate is not reusable. It's hardcoded to always use filteredTimes. It's also putting its results to an array on the outside. Strive for pure functions as much as possible, like math equations. It keeps them reusable, testable and deterministic.


  • Your variable names are vague. A good sign that you're not naming things well enough is when you have to explain to another developer what it is (like what you're doing in the comments). Never be afraid to name things verbosely.


  • You might not need moment.js. What you're doing with moment.js is just intermediary conversion of formats - an unnecessary procedure. When operating with dates and times, it's best to have your data in a format that doesn't need intermediate conversions.


Now simply put, what you're essentially looking for "windows" where the given times overlap. Here's a modified version of your code. The modifications include:



  • The times are all numbers. You don't really need to have the HH:mm format in this operation. If you strip off the : from the time, they're effectively numbers from 0000 to 2359` (with the last 40 mins in each hour missing). This eliminates the need for moment.js.


  • Nested array.forEach(), because for loops are also clunky (you have to keep indexes, do length comparisons, etc.). Plus you're using array.forEach() already anyways.


  • I stored results in an object keyed by the combination of from and to. This way, the lookup doesn't require a very clunky array.find(). Converting it to an array is as simple as iterating over the keys and mapping them to the values.


  • computeWindows is now a pure-ish function. You can now call it anytime, anywhere with any input, and always get a deterministic-ish output (Object.keys() do not guarantee the order of keys, so while the items may be the same, the order may be different by browser).





const ranges = [
from: 1000,
to: 1100
,
from: 1015,
to: 1115
,
from: 1030,
to: 1130
,
from: 1045,
to: 1145
,
from: 1100,
to: 1200
]

const isBetween = (value, start, end) => value > start && value < end

const computeWindows = ranges =>
const index =

ranges.forEach(( from: rFrom, to: rTo ) => )

// Convert results into an array of ranges.
return Object.keys(index).map(k => index[k])


console.log(computeWindows(ranges))








share|improve this answer





















  • I learned a lot! One last thing I'm wondering. You said I could remove the ":" to calculate every time as a number. However, I'm wondering what if I don't remove it. Is it still reliable? Chrome still calculates "12:30">"12:00" as true and "12:00">"12:30" as false
    – Shadrix
    Jun 23 at 14:44






  • 1




    @Shadrix String comparison is alphabetical comparison. "1:30" > "12:30" results totrue which is incorrect from a time point of view. But : is greater than 2 alphabetically. You won't notice this bug immediately, even worse if you hide the values behind variables. Stick to numbers. Even moment.js is probably comparing time in numbers, millisecond timestamps possibly.
    – Joseph
    Jun 23 at 21:16











  • What did you use to develop your personal website? ( will delete this comment when I see you read it, thanks)
    – Billal BEGUERADJ
    Jun 29 at 10:18










Your Answer




StackExchange.ifUsing("editor", function ()
return StackExchange.using("mathjaxEditing", function ()
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
);
);
, "mathjax-editing");

StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: false,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);








 

draft saved


draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f196893%2fcalculate-the-intersections-of-opening-hours%23new-answer', 'question_page');

);

Post as a guest






























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
2
down vote



accepted










  • calculate is not reusable. It's hardcoded to always use filteredTimes. It's also putting its results to an array on the outside. Strive for pure functions as much as possible, like math equations. It keeps them reusable, testable and deterministic.


  • Your variable names are vague. A good sign that you're not naming things well enough is when you have to explain to another developer what it is (like what you're doing in the comments). Never be afraid to name things verbosely.


  • You might not need moment.js. What you're doing with moment.js is just intermediary conversion of formats - an unnecessary procedure. When operating with dates and times, it's best to have your data in a format that doesn't need intermediate conversions.


Now simply put, what you're essentially looking for "windows" where the given times overlap. Here's a modified version of your code. The modifications include:



  • The times are all numbers. You don't really need to have the HH:mm format in this operation. If you strip off the : from the time, they're effectively numbers from 0000 to 2359` (with the last 40 mins in each hour missing). This eliminates the need for moment.js.


  • Nested array.forEach(), because for loops are also clunky (you have to keep indexes, do length comparisons, etc.). Plus you're using array.forEach() already anyways.


  • I stored results in an object keyed by the combination of from and to. This way, the lookup doesn't require a very clunky array.find(). Converting it to an array is as simple as iterating over the keys and mapping them to the values.


  • computeWindows is now a pure-ish function. You can now call it anytime, anywhere with any input, and always get a deterministic-ish output (Object.keys() do not guarantee the order of keys, so while the items may be the same, the order may be different by browser).





const ranges = [
from: 1000,
to: 1100
,
from: 1015,
to: 1115
,
from: 1030,
to: 1130
,
from: 1045,
to: 1145
,
from: 1100,
to: 1200
]

const isBetween = (value, start, end) => value > start && value < end

const computeWindows = ranges =>
const index =

ranges.forEach(( from: rFrom, to: rTo ) => )

// Convert results into an array of ranges.
return Object.keys(index).map(k => index[k])


console.log(computeWindows(ranges))








share|improve this answer





















  • I learned a lot! One last thing I'm wondering. You said I could remove the ":" to calculate every time as a number. However, I'm wondering what if I don't remove it. Is it still reliable? Chrome still calculates "12:30">"12:00" as true and "12:00">"12:30" as false
    – Shadrix
    Jun 23 at 14:44






  • 1




    @Shadrix String comparison is alphabetical comparison. "1:30" > "12:30" results totrue which is incorrect from a time point of view. But : is greater than 2 alphabetically. You won't notice this bug immediately, even worse if you hide the values behind variables. Stick to numbers. Even moment.js is probably comparing time in numbers, millisecond timestamps possibly.
    – Joseph
    Jun 23 at 21:16











  • What did you use to develop your personal website? ( will delete this comment when I see you read it, thanks)
    – Billal BEGUERADJ
    Jun 29 at 10:18














up vote
2
down vote



accepted










  • calculate is not reusable. It's hardcoded to always use filteredTimes. It's also putting its results to an array on the outside. Strive for pure functions as much as possible, like math equations. It keeps them reusable, testable and deterministic.


  • Your variable names are vague. A good sign that you're not naming things well enough is when you have to explain to another developer what it is (like what you're doing in the comments). Never be afraid to name things verbosely.


  • You might not need moment.js. What you're doing with moment.js is just intermediary conversion of formats - an unnecessary procedure. When operating with dates and times, it's best to have your data in a format that doesn't need intermediate conversions.


Now simply put, what you're essentially looking for "windows" where the given times overlap. Here's a modified version of your code. The modifications include:



  • The times are all numbers. You don't really need to have the HH:mm format in this operation. If you strip off the : from the time, they're effectively numbers from 0000 to 2359` (with the last 40 mins in each hour missing). This eliminates the need for moment.js.


  • Nested array.forEach(), because for loops are also clunky (you have to keep indexes, do length comparisons, etc.). Plus you're using array.forEach() already anyways.


  • I stored results in an object keyed by the combination of from and to. This way, the lookup doesn't require a very clunky array.find(). Converting it to an array is as simple as iterating over the keys and mapping them to the values.


  • computeWindows is now a pure-ish function. You can now call it anytime, anywhere with any input, and always get a deterministic-ish output (Object.keys() do not guarantee the order of keys, so while the items may be the same, the order may be different by browser).





const ranges = [
from: 1000,
to: 1100
,
from: 1015,
to: 1115
,
from: 1030,
to: 1130
,
from: 1045,
to: 1145
,
from: 1100,
to: 1200
]

const isBetween = (value, start, end) => value > start && value < end

const computeWindows = ranges =>
const index =

ranges.forEach(( from: rFrom, to: rTo ) => )

// Convert results into an array of ranges.
return Object.keys(index).map(k => index[k])


console.log(computeWindows(ranges))








share|improve this answer





















  • I learned a lot! One last thing I'm wondering. You said I could remove the ":" to calculate every time as a number. However, I'm wondering what if I don't remove it. Is it still reliable? Chrome still calculates "12:30">"12:00" as true and "12:00">"12:30" as false
    – Shadrix
    Jun 23 at 14:44






  • 1




    @Shadrix String comparison is alphabetical comparison. "1:30" > "12:30" results totrue which is incorrect from a time point of view. But : is greater than 2 alphabetically. You won't notice this bug immediately, even worse if you hide the values behind variables. Stick to numbers. Even moment.js is probably comparing time in numbers, millisecond timestamps possibly.
    – Joseph
    Jun 23 at 21:16











  • What did you use to develop your personal website? ( will delete this comment when I see you read it, thanks)
    – Billal BEGUERADJ
    Jun 29 at 10:18












up vote
2
down vote



accepted







up vote
2
down vote



accepted






  • calculate is not reusable. It's hardcoded to always use filteredTimes. It's also putting its results to an array on the outside. Strive for pure functions as much as possible, like math equations. It keeps them reusable, testable and deterministic.


  • Your variable names are vague. A good sign that you're not naming things well enough is when you have to explain to another developer what it is (like what you're doing in the comments). Never be afraid to name things verbosely.


  • You might not need moment.js. What you're doing with moment.js is just intermediary conversion of formats - an unnecessary procedure. When operating with dates and times, it's best to have your data in a format that doesn't need intermediate conversions.


Now simply put, what you're essentially looking for "windows" where the given times overlap. Here's a modified version of your code. The modifications include:



  • The times are all numbers. You don't really need to have the HH:mm format in this operation. If you strip off the : from the time, they're effectively numbers from 0000 to 2359` (with the last 40 mins in each hour missing). This eliminates the need for moment.js.


  • Nested array.forEach(), because for loops are also clunky (you have to keep indexes, do length comparisons, etc.). Plus you're using array.forEach() already anyways.


  • I stored results in an object keyed by the combination of from and to. This way, the lookup doesn't require a very clunky array.find(). Converting it to an array is as simple as iterating over the keys and mapping them to the values.


  • computeWindows is now a pure-ish function. You can now call it anytime, anywhere with any input, and always get a deterministic-ish output (Object.keys() do not guarantee the order of keys, so while the items may be the same, the order may be different by browser).





const ranges = [
from: 1000,
to: 1100
,
from: 1015,
to: 1115
,
from: 1030,
to: 1130
,
from: 1045,
to: 1145
,
from: 1100,
to: 1200
]

const isBetween = (value, start, end) => value > start && value < end

const computeWindows = ranges =>
const index =

ranges.forEach(( from: rFrom, to: rTo ) => )

// Convert results into an array of ranges.
return Object.keys(index).map(k => index[k])


console.log(computeWindows(ranges))








share|improve this answer













  • calculate is not reusable. It's hardcoded to always use filteredTimes. It's also putting its results to an array on the outside. Strive for pure functions as much as possible, like math equations. It keeps them reusable, testable and deterministic.


  • Your variable names are vague. A good sign that you're not naming things well enough is when you have to explain to another developer what it is (like what you're doing in the comments). Never be afraid to name things verbosely.


  • You might not need moment.js. What you're doing with moment.js is just intermediary conversion of formats - an unnecessary procedure. When operating with dates and times, it's best to have your data in a format that doesn't need intermediate conversions.


Now simply put, what you're essentially looking for "windows" where the given times overlap. Here's a modified version of your code. The modifications include:



  • The times are all numbers. You don't really need to have the HH:mm format in this operation. If you strip off the : from the time, they're effectively numbers from 0000 to 2359` (with the last 40 mins in each hour missing). This eliminates the need for moment.js.


  • Nested array.forEach(), because for loops are also clunky (you have to keep indexes, do length comparisons, etc.). Plus you're using array.forEach() already anyways.


  • I stored results in an object keyed by the combination of from and to. This way, the lookup doesn't require a very clunky array.find(). Converting it to an array is as simple as iterating over the keys and mapping them to the values.


  • computeWindows is now a pure-ish function. You can now call it anytime, anywhere with any input, and always get a deterministic-ish output (Object.keys() do not guarantee the order of keys, so while the items may be the same, the order may be different by browser).





const ranges = [
from: 1000,
to: 1100
,
from: 1015,
to: 1115
,
from: 1030,
to: 1130
,
from: 1045,
to: 1145
,
from: 1100,
to: 1200
]

const isBetween = (value, start, end) => value > start && value < end

const computeWindows = ranges =>
const index =

ranges.forEach(( from: rFrom, to: rTo ) => )

// Convert results into an array of ranges.
return Object.keys(index).map(k => index[k])


console.log(computeWindows(ranges))








const ranges = [
from: 1000,
to: 1100
,
from: 1015,
to: 1115
,
from: 1030,
to: 1130
,
from: 1045,
to: 1145
,
from: 1100,
to: 1200
]

const isBetween = (value, start, end) => value > start && value < end

const computeWindows = ranges =>
const index =

ranges.forEach(( from: rFrom, to: rTo ) => )

// Convert results into an array of ranges.
return Object.keys(index).map(k => index[k])


console.log(computeWindows(ranges))





const ranges = [
from: 1000,
to: 1100
,
from: 1015,
to: 1115
,
from: 1030,
to: 1130
,
from: 1045,
to: 1145
,
from: 1100,
to: 1200
]

const isBetween = (value, start, end) => value > start && value < end

const computeWindows = ranges =>
const index =

ranges.forEach(( from: rFrom, to: rTo ) => )

// Convert results into an array of ranges.
return Object.keys(index).map(k => index[k])


console.log(computeWindows(ranges))






share|improve this answer













share|improve this answer



share|improve this answer











answered Jun 22 at 22:31









Joseph

22.1k21833




22.1k21833











  • I learned a lot! One last thing I'm wondering. You said I could remove the ":" to calculate every time as a number. However, I'm wondering what if I don't remove it. Is it still reliable? Chrome still calculates "12:30">"12:00" as true and "12:00">"12:30" as false
    – Shadrix
    Jun 23 at 14:44






  • 1




    @Shadrix String comparison is alphabetical comparison. "1:30" > "12:30" results totrue which is incorrect from a time point of view. But : is greater than 2 alphabetically. You won't notice this bug immediately, even worse if you hide the values behind variables. Stick to numbers. Even moment.js is probably comparing time in numbers, millisecond timestamps possibly.
    – Joseph
    Jun 23 at 21:16











  • What did you use to develop your personal website? ( will delete this comment when I see you read it, thanks)
    – Billal BEGUERADJ
    Jun 29 at 10:18
















  • I learned a lot! One last thing I'm wondering. You said I could remove the ":" to calculate every time as a number. However, I'm wondering what if I don't remove it. Is it still reliable? Chrome still calculates "12:30">"12:00" as true and "12:00">"12:30" as false
    – Shadrix
    Jun 23 at 14:44






  • 1




    @Shadrix String comparison is alphabetical comparison. "1:30" > "12:30" results totrue which is incorrect from a time point of view. But : is greater than 2 alphabetically. You won't notice this bug immediately, even worse if you hide the values behind variables. Stick to numbers. Even moment.js is probably comparing time in numbers, millisecond timestamps possibly.
    – Joseph
    Jun 23 at 21:16











  • What did you use to develop your personal website? ( will delete this comment when I see you read it, thanks)
    – Billal BEGUERADJ
    Jun 29 at 10:18















I learned a lot! One last thing I'm wondering. You said I could remove the ":" to calculate every time as a number. However, I'm wondering what if I don't remove it. Is it still reliable? Chrome still calculates "12:30">"12:00" as true and "12:00">"12:30" as false
– Shadrix
Jun 23 at 14:44




I learned a lot! One last thing I'm wondering. You said I could remove the ":" to calculate every time as a number. However, I'm wondering what if I don't remove it. Is it still reliable? Chrome still calculates "12:30">"12:00" as true and "12:00">"12:30" as false
– Shadrix
Jun 23 at 14:44




1




1




@Shadrix String comparison is alphabetical comparison. "1:30" > "12:30" results totrue which is incorrect from a time point of view. But : is greater than 2 alphabetically. You won't notice this bug immediately, even worse if you hide the values behind variables. Stick to numbers. Even moment.js is probably comparing time in numbers, millisecond timestamps possibly.
– Joseph
Jun 23 at 21:16





@Shadrix String comparison is alphabetical comparison. "1:30" > "12:30" results totrue which is incorrect from a time point of view. But : is greater than 2 alphabetically. You won't notice this bug immediately, even worse if you hide the values behind variables. Stick to numbers. Even moment.js is probably comparing time in numbers, millisecond timestamps possibly.
– Joseph
Jun 23 at 21:16













What did you use to develop your personal website? ( will delete this comment when I see you read it, thanks)
– Billal BEGUERADJ
Jun 29 at 10:18




What did you use to develop your personal website? ( will delete this comment when I see you read it, thanks)
– Billal BEGUERADJ
Jun 29 at 10:18












 

draft saved


draft discarded


























 


draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f196893%2fcalculate-the-intersections-of-opening-hours%23new-answer', 'question_page');

);

Post as a guest













































































Popular posts from this blog

Greedy Best First Search implementation in Rust

Function to Return a JSON Like Objects Using VBA Collections and Arrays

C++11 CLH Lock Implementation