0

Am doing a script in which have need of know if the store is open or closed, depending on the time local. Currently, I get the data of an api, which I keep in my database and call it via an Ajax request. The data that return are (equal that which I get):

["Mo-Sa 11:00-14:30", "Mo-Th 17:00-21:30", "Fr-Sa 17:00-22:00"]

I have been assessing the possibility of converting it as well (I still have to see how to do it):

{
    "monday": ["11:00-14:30", "17:00-21:30"],
    "tuesday": ["11:00-14:30", "17:00-21:30"],
    "wednesday": ["11:00-14:30", "17:00-21:30"],
    "thursday": ["11:00-14:30", "17:00-21:30"],
    "friday": ["11:00-14:30", "17:00-22:00"],
    "saturday": ["11:00-14:30", "17:00-22:00"],
    "sunday": null
}

I've seen examples in these questions:

Create a function to check if a business is open and write text to html

Determine If Business Is Open/Closed Based On Business Hours (php)

Before programming code with any routine for this, I want to know if anyone knows any way to make it simple or has seen some portion of code on the web; to not reinvent the wheel. Thanks a lot.

Best regards

Community
  • 1
  • 1
Anto
  • 313
  • 1
  • 3
  • 13
  • So what have you tried so far? I suggest you at least try something before seeking help... – NewToJS Dec 29 '16 at 15:59
  • I would start by not storing that friendly-looking data like `Mo-Sa 11:00-14:30`, and go with your idea of storing data by day. That friendly-looking data can be display-only, or possibly parsed if a user enters it, but any queries against the data will be much easier if it's stored in your database very simply. – Joe Enos Dec 29 '16 at 16:03

2 Answers2

0

With opening times, I prefer to convert all values to be compared to full minutes (hour*60 + minutes). That way it's easier to compare to actual times.

Having minutes as starting point, I would do the conversion somewhat different by using an array for each weekday (with the same index as returned by Date.getDay() ), with each day containing sub-arrays with the open start-end times in minutes (start and end also in sub arrays, or in an object)

const arr= ["Mo-Sa 11:00-14:30", "Mo-Th 17:00-21:30", "Fr-Sa 17:00-22:00"],
 days = ['Su','Mo','Tu','We', 'Th', 'Fr', 'Sa'], //start with sunday to be compatible with Date.getDay
  times = Array.from(days, (d,i) => []),
  getDay = (s,i) => days.indexOf(s.slice(i,i+2)), //helper function for parsing day name
  getMinutes = s => s.split(':').reduce((m, n) => m * 60 + parseInt(n,10),0); //helper to store time in minutes of day
 
 //convert to new format 
 for(let s of arr){
    let d = getDay(s,0), end = getDay(s,3);
    while(true){     
      times[d].push( s.slice(6).split('-').map(getMinutes));
      if(d===end)break;
      d = ++d % 7; //the %7 makes it possible to have ranges as Th-Mo
    }
 }
 
 //now times contains an array with a day in each index, containing subarrays of the opening times in minutes
 function isOpen(dt){  
   let mins = dt.getHours() * 60 + dt.getMinutes();
   return times[dt.getDay()].some(a=>a[0] <= mins && a[1] >= mins)
 }
 
 
 //----------------------------------------------------------
 //test functions only
 console.log('Is open now: ' , isOpen(new Date()));
 function test(dts){let dt = new Date(dts); console.log(days[dt.getDay()], dts,':', isOpen(dt));}
 test('2016/12/29 8:00'); //th
 test('2016/12/29 10:59');
 test('2016/12/29 11:00');
 test('2016/12/29 12:00'); 
 test('2016/12/30 12:00'); //fr
 test('2017/1/1 12:00'); //su
 test('2016/12/29 21:45'); //th
 test('2016/12/30 21:45'); //fr
Me.Name
  • 12,259
  • 3
  • 31
  • 48
-1
var dates=yourdateobj;
//its easier to work with numbers then string for example (1-3 is easier then mo-wed)
var daytoindex={"Mo":1,"Tu":2,"Wed":3,"Thu":4,"Fr":5,"Sat":6,"Sun":7};
//the better structured table: 
var destructdates=[];
//for each old timestring:
dates.forEach((e,i)=>{
  //destructure timestring
  e=e.split(" ");
  var days=e[0].split("-");
  var hours=e[1];
  //add time to all days inbetween (1-3 (Mo-Wed) is 1,2,3 (Mo,Tue;Wed)
  for(var i=daytoindex[days[0]];i<=daytoindex[days[1]];i++){
    //the day is an array,add the open hours
    destructdates[i]=destructdates[i]||[];
    destructdates[i].push(hours);
  }
});

That creates your second object ( similar):

destructdates:
[
1:["12:33-15:44","12:33-0:30"] //Mo
2:...
]

Now you can do this:

function open(day,hour,second){
//get the todays times Array
var dayhours=destructdates[daytoindex[day]];
 //if now falls into one of the times:   
return dayhours.some((e,i)=>{

   //destructure the times:
   e=e.split("-");
   var start=e[0].split(":");
   var starthour= +start[0];
   var startminute= +start[1];
   var end=e[1].split(":");
   var endhour= +end[0];
   var endminute= +end[1];

   //check:
   if(starthour<=hour && startminute<=minute && endhour>=hour &&endminute>=minute){
     return true;
    }
return false;
});
}

Use like this:

alert(open("Tu",12,33)?"Open":"Close");    

Problems/TODO ( i dont do all of your work): Sunday-Friday wont work, the for loop will fail. You need to convert the todays date into the open arguments somehow.

Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151