Create a function to check if a business is open - javascript

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

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

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.

Related

How to return epoch of all midnights in given time span?

I have a time span between two epoch times (in seconds). I want a function that returns the epoch times (in seconds) of all midnights within that time span.
In pseudocode I would want something like this:
const epoch_start = 1600000;
const epoch_end = 16040000;
function getMidnights(start, end){
// do your magic
}
console.log(getMidnights(epoch_start, epoch_end));
I would expect the return of that function to look like this: [1600020, 1600400] (these are just example values).
What would be the most efficient way to do this?
My ideas were: get unique list of days within range and return their midnight.
You might step by day rounding by day:
const epoch_start = 1600000000;
const epoch_end = 1600400000;
const day = 86400;
function getMidnights(start, end){
midnites = [];
while (start < end) {
midnites.push((start/day + .5|0)*day);
start += day;
}
return midnites;
}
console.log(getMidnights(epoch_start, epoch_end))
console.log('* check it *')
console.log(getMidnights(epoch_start, epoch_end).map(t => new Date(t*1e3)));

MomentJS and JS Date objects not referring to the same hour

I've got a server instance (NodeJS) that receives a set of objects, and schedules them for sending push notifications to users.
Some of these objects, are periodic, and this periodicity is handled by a string like this:
90=>Mon&Tue&Thu=>16:00
Which is read as:
offset_minutes=>days_of_the_week=>initial_hour
Then, what I do is to check whether the current day matches one of the given days in the string, and then, modify the date to the given hour in the "initial_hour", and finally, substract the "offset_minutes" amount of minutes from the Date object.
Seems straightforward until now, right? Well, not that much. Let's first see the code:
const isToday = weekDays.split("&")
.map(a => {
switch (a) {
case 'Mon': return 1;
case 'Tue': return 2;
case 'Wed': return 3;
case 'Thu': return 4;
case 'Fri': return 5;
case 'Sat': return 6;
case 'Sun': return 7;
}
})
.some(v => v == currentDay);
if (isToday) {
let finalDate = moment(today)
.set("hour", Number(hour))
.set("minute", Number(mins));
if (offset) {
finalDate.subtract('minutes', Number(offset));
}
return finalDate.toDate();
Everything works well, until I do the MomentJS transformations. When I output a Date object with the ".toDate()" method, this object is always set to 2 hours before the expected time. But if I use the .toISOString() method, I get the proper time for all the occurrencies.
I guess that something is wrong with my Date objects, setting them up at a different timezone than the one I have. A couple of examples:
For the string 90=>Mon&Tue&Thu=>16:00 I get the Date object: 2019-10-14T14:00:11.852Z
For the string 30=>Mon&Tue&Wed&Thu&Fri&Sat&Sun=>18:30 I get the Date object: 2019-10-14T16:30:11.866Z
I would like to know what's the explanation for such a behavior, and if I can do something to change it so the normal Javascript Date object points to the same hour than my momentjs object, or the .toISOString() output.
Thank you!
The posted code is incomplete and doesn't demonstrate the issue described.
I've reimplemented the code without moment.js as best I can and simplified it. It seems to work fine:
function parseThing(s) {
// Parse input string
let b = s.split('=>');
let offset = +b[0];
let days = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
let weekDays = b[1].split('&').map(day => days.indexOf(day));
let [hr, min] = b[2].split(':');
// Get a date for today
let date = new Date();
// If today included, return an adjusted date
if (weekDays.includes(date.getDay())) {
date.setHours(hr, min, 0, 0);
if (offset) {
date.setMinutes(date.getMinutes()+ Number(offset));
}
return date;
}
// If today isn't included, return null
return null;
}
let s0 = '90=>Mon&Tue&Thu=>16:00';
let s1 = '0=>Mon&Tue&Wed&Thu&Fri&Sat&Sun=>18:30';
console.log(parseThing(s0).toString());
console.log(parseThing(s1).toString());
Where the local day is one of those in the string (Mon, Tue, Thu) it returns a Date equivalent to a local time of 17:30, which is 90 minutes offset from 16:00, which seems to be correct.
PS I've changed Sunday to 0 as I can't see any rationale for it to be 7. Also seconds and milliseconds are zeroed too.

How to get the Australian Time Zone using Javascript? (Not JQuery)

I am trying to help a friend to get the Australian Time Zone for the University Assignment and finding difficulty.
Could someone point us in the right direction?
Thank you!
<script>
function Timezone() {
var x = new Date();
var currentTimeZoneOffsetInHours = x.getTimezoneOffset() / 60;
document.getElementById("add").innerHTML = currentTimeZoneOffsetInHours;
}
</script>
<p id="add"></p>
You simply use
let AuDate = new Date().toLocaleString("en-US", {timeZone: "Australia/Sydney"});
By looking at your code, looks like you are trying to get the current date and time of an Australian timezone. Lets say you want Australian Eastern Standard Time (AEST) and you want the date displayed how they would in Australia DD-MM-YYYY then do the following:
var timestamp_UTC = new Date();
var readable_timestamp_AEST = timestamp_UTC.toLocaleDateString("en-AU", {timeZone: "Australia/Sydney"}).replace(/\//g, "-") + ' ' + somestamp.toLocaleTimeString("en-AU", {timeZone: "Australia/Sydney"});
"en-AU" is the locales argument which tells the toLocalDateString to display the date as DD-MM-YYYY and the second argument is for options (timeZone is just one such possible option). Info about toLocalDateString function can be found here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleDateString
Here is some information about the Date() function https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date
Hope this clears up a few things around getting times and dates from the Date() function.
I think i understand what you mean. But before that i'd like to make 2 points:
1: The Timezone() function should be called somewhere.
<script>
function Timezone() {
var x = new Date();
var currentTimeZoneOffsetInHours = x.getTimezoneOffset() / 60;
document.getElementById("add").innerHTML = currentTimeZoneOffsetInHours;
}
Timezone();
</script>
2: The convention usually is that methods start with a lower case letter. Maybe updateTimezone() would be more appropriate.
Your question can be interpreted in 2 ways now:
you want your timezone's offset in hours and for this the code above should work. getTimezoneOffset() is the way to go.
you want a human readable name of your timezone, as you can see on my site currentmillis.com (in my case it says GTB Summer). You can look in my source code to see how i achieve this:
var s = date.toString();
var iOfP = s.indexOf('('); // index of parenthesis
if (iOfP < 0) {
s = s.substring(s.lastIndexOf(' ') + 1);
} else {
s = s.substring(iOfP+1, s.length-1);
}
if (s.length > 4 && s.lastIndexOf(" Time") == s.length-5){
s = s.substring(0, s.length-5);
}
timezoneM.innerHTML = s;
This works because when you call toString() on the date the result should contain the full name of your timezone: w3schools.com/jsref/jsref_tostring_date.asp

using the time as a dynamic variable to compare values

I am working on programming a page in JS that grabs calendar data from an outside source, imports it into a multidimensional array and uses it to display who is currently working along with their photo, phone number, etc.
Right now I have it set up so that the page reloads every 15 minutes. I'd prefer to have this all done dynamically so that when, say, the clock strikes 5pm the page knows to update without having to wait until the 15 minute refresh is triggered.
All of the work times are pulled from the other calendar in 24 hour format (so 5pm is 1700).
Here's how I'm generating the current time to compare with the start/end times in the calendar:
//Get the current date and time
var dateTime = new Date();
var month = dateTime.getMonth() + 1;
var day = dateTime.getDate();
var dayOfWeek = dateTime.getDay();
var year = dateTime.getYear() + 1900;
//converting hours and minutes to strings to form the 24h time
var hours = dateTime.getHours().toString();
if (hours.length === 1) {
var hours = '0' + hours
};
var minutes = dateTime.getMinutes().toString();
if (minutes.length === 1) {
var minutes = '0' + minutes
};
var time = hours + minutes;
//convert the 24h time into a number to read from later
var timeNumber = parseInt(time);
I then use if statements to compare the start/end times from the imported schedule with timeNumber to determine who is currently working and push that to an array that is eventually displayed on the page with this code:
//figure out who is currently working and put them in the workingNow array
var workingNow = [];
for (i = 0; i < workingToday.length; i++){
//convert time strings to numbers to compare
var startTime = parseInt(workingToday[i][7]);
var endTime = parseInt(workingToday[i][8]);
//compare start and end times with the current time and add those who are working to the new list
if(startTime < timeNumber && timeNumber < endTime){
workingNow.push(workingToday[i]);
}
};
I guess I have just been trying to figure out how to make this comparison of the data in an array with the current time something that is dynamic. Is this possible or would I need to go about this in a completely different way from the ground up?
You should have a look at momentjs. This is a really good library to handle all sort of time and date manipulation.
http://momentjs.com/

Cannot print message according to time

I've three different times, two of them are in string forms (time1 and time2) and one from system date currDate. Next step according to the one of two above times I want to print messages when the system date reaches one of them. For this I've function callEachMinute that calls each minute to get system time (but here in code I did not include the whole procedure). Here is the current status of the code:
Script:
function callEachMinute() {
var currDate = new Date();
var time_1 = '8:30';
var time_2 = '23:00';
timeComparison(currDate, time_1, time_2)
}
function timeComparison(currTime, time1, time2) {
// Time 1 formatting
var t1 = new Date();
var parts1 = time1.split(":");
t1.setHours(parts1[0],parts1[1]);
// Iftor-Time formatting
var t2 = new Date();
var parts2 = timeI.split(":");
t2.setHours(parts2[0],parts2[1]);
/* Notification procedure */
if (currTime == t1) {
// Message for Time1
alert("Time 1 is reached");
}
if (currTime == t2) {
// Message for Time2
alert("Time 2 is reached");
}
}
Problem:
When the system time is reached one of times (time1 or time2) nothing happens. Any solution for this problem?
There are a few things that could be problematic here.
You set up a Date object then want to compare it to currTime:
if (currTime == t1) {
unfortunatley Javascript's == operator when applied to objects compares two objects to see if they are references to the same object, so even if currTime and t1 contained exactly the same time this check would evaluate to false since they are different instances. You could do this by converting to a string:
if (currTime.toString() == t1.toString) {
which would work if the string representations for each data work out the same.
However, a more straight forward approach might be to tackle this the other way around - extract the hours and minutes from currTime, build a string and compare that to your time strings. Something like:
// in timecomparison function
var hrs = currTime.getHours();
var mins = currTime.getMinutes();
var now = hrs+":"+mins
// now do comparisons
if (now == time1 ) {
....
}
and so on.

Categories

Resources