I have a todo list with a 'done' button with each todo. Once the 'done' button is clicked by the user, it will be disabled. The button should be enabled at 2 am everyday.
I could disable the button, but i am unable to enable it at 2 am. Here is my code.
$scope.doneItem = function(todo) {
todo.stopSpam = true;
$interval(callAtInterval, 3000);
function callAtInterval(){
var date = new Date();
if (date.getHours() === 2 && date.getMinutes() ===0){
todo.stopSpam = false;
}
}
};
Based on the fact that you're trying to do this with intervals, I'm going to assume you're going to be leaving the page with your app up. What you do in your example technically can work, but only if the interval falls exactly on 2 AM (ignoring seconds and milliseconds). The easiest accurate way I can think of is to just do a quick calculation of the interval between "now" and 2 AM.
var date = new Date(); //This gets the current date and time
var timeInterval = new Date(date.getFullYear(), date.getMonth(), date.getDate()+1,2)-date;
//This gets the difference between the time and 2 AM the next day.
//Now you can make an accurate interval call
$interval(callAtInterval, timeInterval);
This way will limit it to 2:00 AM the next day. If, however, for 1 AM you didn't want to skip that day's 2 AM to enable it, you'd make one more quick check.
var timeInterval;
if(date.getHours()>2)
timeInterval = new Date(date.getFullYear(), date.getMonth(), date.getDate(),2)-date;
else
timeInterval = new Date(date.getFullYear(), date.getMonth(), date.getDate()+1,2)-date;
Related
Let's imagine that a local bakery has a website that shows its working hours along with a tag "Open" or "Closed". This tag needs to change based on the hours of operation.
The solution that I thought of was to have two states:
for status of working hours (open/closed)
for current time
For the second one I used a solution that I found for online clock:
const [date, setDate] = useState(new Date());
useEffect(() => {
let timer = setInterval(() => setDate(newDate()), 1000);
return function cleanup() {
clearInterval(timer);
};
});
And for changing open/closed state I thought of using this handler:
const handleStatus = () => {
let openHour = new Date();
let closeHour = new Date();
openHour.setHours(9, 0, 0);
closeHour.setHours(18, 30, 0);
if (date > openHour) {
//CLOSED
} else {
//OPEN
}
};
The problem with this approach is that it only works for the state that I am located at and not the other timezone. The goal is to keep the state change for only a specific timezone, so the user that is located in NYC at 9pm will see that the bakery is still open since it is 6pm in LA and it closes only at 6:30pm. How do I go around that? If there is any other approach please let me know!
As of now, JavaScript standard library does not have a concept of ZonedDateTime. Until it becomes available, you can calculate the timezone offset manually and operate on the Date objects in UTC.
// Calculate timezone offset of America/Los_Angeles
utcDate = new Date();
utcDate.setHours(0, 0, 0, 0);
strDateLA = utcDate.toLocaleString("en-US", {
timeZone: "America/Los_Angeles",
});
offset = (new Date(strDateLA) - utcDate) / (1000 * 60 * 60);
console.log(offset);
Now that you have the timezone offset, you can convert the opening and closing hours into UTC date-time.
openHourUTC = new Date();
openHourUTC.setHours(9, 0, 0, 0);
// Opening hour in UTC
openHourUTC = openHourUTC - offset;
closeHourUTC = new Date();
closeHourUTC.setHours(18, 30, 0, 0);
// Closing hour in UTC
closeHourUTC = closeHourUTC - offset;
Note: If the timezone offset is negative e.g. -8, the above code snippet calculates openHourUTC = openHourUTC - (-8) => openHourUTC = openHourUTC + 8.
Now, you can do:
if (date >= openHourUTC && date < closeHourUTC) {
// OPEN
} else {
// CLOSED
}
Maybe you should try to use the browser's timezone instead of the local device's timezone. You can get the browser's timezone with the Intl.DateTimeFormat().resolvedOptions().timeZone method.
You can use this method to update the working hours status based on the browser's timezone:
const handleStatus = () => {
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
// Set the open and close hours based on the timezone
let openHour, closeHour;
if (timezone === 'America/Los_Angeles') {
openHour = new Date();
openHour.setHours(9, 0, 0);
closeHour = new Date();
closeHour.setHours(18, 30, 0);
} else {
// Set the open and close hours for other timezones here
}
if (date > openHour && date < closeHour) {
// The bakery is open
} else {
// The bakery is closed
}
};
This way, the working hours status will always be based on the browser's timezone, regardless of the local device's timezone.
Alternatively, you could use a server-side solution to get the correct time for the browser's timezone. This would involve making a server-side API call to get the current time in the browser's timezone, and then using that time to update the working hours status. This approach would be more accurate, as it takes into account daylight saving time and other factors that can affect the local device's time. However, it would require setting up a server and making API calls, which may not be necessary if you only need to display the working hours status on a static website.
I hope this helps you some ways.
I'm new to node js . I want to make a bot that calculates our study time and sends it in our channel
So ,when someone from our server message !login is should start the stopwatch and when he types !logout it should stop the stopwatch and the time to the previous and show the total time
Please help me , I want it done as soon as possible
One way to do that would be to create a Collection in the client, store the time when the user sends !login and then when the user sends !logout, fetch the started date from the client, calculate the time used, and then set the Collection to null. However one disadvantage of that is the fact that once the bot restarts, all the data is lost. But since I have no idea if you have any database already set up, we can use Collections for now. The completed code might look something like this:
const { Collection } = require('discord.js')
// ...
client.userStudyTime = new Collection()
client.on("messageCreate", (message) => {
if (message.author.bot) return;
if (message.content === '!login') { // Check if the message's content was !login
const time = new Date() // Get the login time
client.userStudyTime.set(message.author.id, time.getTime()) // Set the time
}
if (message.content === '!logout') { // Check if the message's content was !logout
const userTime = client.userStudyTime.get(message.author.id) // Get the user's login time
if (!userTime) return message.channel.send('You are not logged in!') // Check if the user had logged in
const time = new Date().getTime() // Get the logout time
const diff = time - userTime // Calculate the difference
const hours = Math.round(diff / 1000 / 60 / 60) // Get the hours
const minutes = Math.round(diff / 1000 / 60) // Get the minutes
const seconds = Math.round(diff / 1000) // Get the seconds
message.channel.send(`You studied for ${hours}hrs, ${minutes}min, ${Math.round(seconds)}sec`) // Reply back
client.userStudyTime.set(message.author.id, null) // Set the collection to null
}
});
// ...
It would be unwise to have something like a stopwatch.
You want something that will store the user and the time they login, and then when the log out, calculate the time difference and send that.
That can be achieved with either a database, or a simple JSON file.
Something you can do is save a timestamp when using !login with the Date.now() function, whether it be in a client collection or a database. And compare it to the timestamp when they use !logout, the difference between the two would be the amount of seconds they were logged in.
Date.now() Function
Date.now(); // outputs a timestamp
Output:
1653579416
Login Command
in the logout command, you're going to want to use the Date.now() function and set it in your database or your collection under the user that used the command.
Logout Command
in the logout command you want to go back to the login timestamp, and subtract the current timestamp by the saved one, and the difference will be how many seconds they were logged in for.
Example
var loggedInStamp // 1653579416 // you'll want to get this from wherever you saved it
var loggedOutStamp = Date.now() // 1653580205 // current timestamp
// subtract 1653580205 by 1653579416 which equals 789 //
// aka logged in for 789 seconds //
let amountTime = loggedOutStamp - loggedInStamp
return amountTime
/* this is what you want to add to the total time logged in */
This will make your database save the total time logged in seconds, there are plenty of modules or algorithms to convert seconds to minutes, hours, days...
Here is a code example for converting seconds to hours and minutes:
function secondsToHms(d) {
d = Number(d);
var h = Math.floor(d / 3600);
var m = Math.floor(d % 3600 / 60);
var s = Math.floor(d % 3600 % 60);
var hDisplay = h > 0 ? h + (h == 1 ? " hour, " : " hours, ") : "";
var mDisplay = m > 0 ? m + (m == 1 ? " minute, " : " minutes, ") : "";
var sDisplay = s > 0 ? s + (s == 1 ? " second" : " seconds") : "";
return hDisplay + mDisplay + sDisplay;
}
This is a better way to get the amount of time logged in instead of using a stopwatch.
I'm implementing a Save feature on a form I'm creating in React. When a User clicks save on a form, I want them to type the username/password. The next time that same user tries to save, if it's been under 15 minutes, I want them to not have to sign the save username/password. If it's over 15, I want them to authenticate again.
I stumbled across this code on a different stackoverflow question about timeouts.
calculateHours(date1 , expireTime){
const dateOne = date1;
const dateTwo = new Date();
const dateOneObj = new Date(dateOne);
const dateTwoObj = new Date(dateTwo);
const hours = Math.abs(dateTwoObj - dateOneObj)/ 36e5;
const minutes = hours/ 36e5;
return expireTime > hours ? true : false
}
Code for defining the 15 minute timeout currently.
if(this.calculateHours(localStore.time , 15)){
this.wrappedClickHandler()
This is for a 15 minute timeout, but the code is really sloppy and ugly and I was wondering if anyone has a better way of implementing this?
Unless you use a library to handle time, it is not so easy to get better code: You can do some better naming, but the operation is similar:
const isExpired = (startDate, minutes) => {
startDate = startDate instanceof Date ? startDate : new Date(startDate)
const diff = new Date() - new Date(startDate)
const minutesDiff = Math.floor((diff/1000)/60);
return minutesDiff >= minutes
}
You can use setTimeout. The function will execute after a given time
setTimeout(() => {
...your necessary code for requiring user to enter username & password...
}, 15 * 60 * 1000) // since time is to be written in milliseconds
When dealing with time, I always use epochMilli.new Date().getTime() then plus 15 minutes is (15*60*1000) milliseconds to be epochExpiresAt kept somewhere(redux?) And then you use the isExpired Function to check every time user click save.
const isExpired = (epochExpiresAt) => epochExpiresAt > new Date().getTime()
Hi I want to make a function that generates available time slots. It should generate the time slots while keeping in mind that the time slot can't overlap with an already made appointment.Before the time slots are generated a user can specify which kind of appointment to schedule. Each appointment sort has a duration. So it should also check if the time slot added with the duration doesn't overlap.
I'm struggling to make this all working so far I get time slots but it seems to only checks the start of an already made appointment. I'm kind of running in circles here and would love for some advice or part solutions that I can implement to make my idea work
const GenerateAvailableTimeSlots = (start, serviceObject, allAppointments) => {
const moment = extendMoment(Moment);
var x = {
nextSlot: 15,
appointmentsOfThatDay: [],
startTime: '8:00',
endTime: '20:00'
};
// function to filter only the appointment that occur on specified day --> ( start )
let filterAppointments = (allAppointments, start) => {
let results = [];
let filterAppoinments = allAppointments.filter(appoinment => appoinment.date === start.format('MMMM Do YYYY'));
filterAppoinments.map(appoinment => results.push([appoinment.start.format('HH:mm'), appoinment.end.format('HH:mm')]))
console.log("results", results);
return results;
};
x.appointmentsOfThatDay = filterAppointments(allAppointments, start)
console.log("appointmentsOfThatDay", x.appointmentsOfThatDay)
var slotTime = moment(x.startTime, "HH:mm");
var endTime = moment(x.endTime, "HH:mm");
// function to check time slot overlaps with already made appointments
function OverlapsScheduledAppointment(slotTime, appointments) {
//added duration to timeslot so I could check if a suggested timeslot + the duration also doesn't overlap with already made appointment
var slotTimeWithDuration = slotTime.clone().add(serviceObject.hours, 'hours').add(serviceObject.minutes, 'minutes');
// I don't know where I also could check for slotTimeWithDuration overlap
return appointments.some((br) => {
console.log(slotTime >= moment(br[0], "HH:mm") && slotTime < moment(br[1], "HH:mm"));
return (slotTime >= moment(br[0], "HH:mm") && slotTime < moment(br[1], "HH:mm"));
});
}
let times = [];
while (slotTime < endTime) {
if (!OverlapsScheduledAppointment(slotTime, x.appointmentsOfThatDay)) {
times.push(slotTime.format("HH:mm"));
}
slotTime = slotTime.add(x.nextSlot, 'minutes');
}
return times;
};
I've found the answer to my question.
I was going in the right direction with the above code but in order for generating available time slots that keep in mind the duration of the service you want to schedule and the appointment that are already scheduled.
I had to change this line of code:
// this line just pushes the filtered appointment for a specific day
filterAppoinments.map(appoinment => results.push([appoinment.start.format('HH:mm'), appoinment.end.format('HH:mm')]))
To this
// this line filters the appointment for a specific day and also adds the duration of a service to the start time of an already scheduled appointment. This way when I check if a generated time slot for a service will overlap with an already scheduled appointment it filters out the ones that will overlap
filterAppoinments.map(appoinment => results.push([appoinment.start.clone().subtract(serviceObject.hours, 'hours').subtract(serviceObject.minutes, 'minutes').format('HH:mm'), appoinment.end.format('HH:mm')]))
My question is: how can I make a command clock (when you execute !count and after 4 minutes you type !time and it says 4 minutes!) in discord.js
const Discord = require('discord.js');
exports.run = (client, message) => {
var af = 0;
a = setInterval(function(){
console.log("Hi");
af = af+1;
if(af == 25){
clearInterval(a);
}
console.log(af);
}, 60000);
};
exports.help = {
name: 'time',
description: 'time?',
usage: 'time'
};
I would do it like this: when you execute !count you save the server time, when you execute !time you send back the difference between those two dates.
Pseudo-code:
var date;
if (command == 'count') {
date = new Date();
message.reply("Done");
}
if (command == 'time') {
let result = require('pretty-ms')(date ? (new Date() - date) : 0);
message.reply(result);
}
I'm using the pretty-ms npm package to format milliseconds: docs & live demo.
When someone calls !count, store the current Date somewhere. new Date() - date will give you the difference between the current time and the time you stored, in milliseconds.
Please note that if the commands are in different files, as it seems by the code you posted, you'll need to store the date in a location accessible to both files: one of the solutions is to store the date as a global variable.
// by '...' I mean that you can put it wherever you want in the global object
global['...'].date = new Date():
new Date() - global['...'].date
Edit: Date class explanation
When you create a new Date, it saves the time at the moment you create it. It's like saying "!count was executed at 04:20". When you want to check how much time has passed, you need to calculate the first date minus the current date: "!count was executed at 04:20. Now it's 05:40, so the difference is 05:40 - 04:20 = 01:20: it's 1 hour and 20 minutes since you first executed !count". That translates to new Date() - past_date = time_passed.
Since dates are stored in milliseconds that difference is in milliseconds: if you want to make it more readable, you can format it by using a function as the 'pretty-ms' package, or similar ones.
The key concept is:
When !count is called, you save a new Date() to lock that point in time
When !time is called, you get the difference by doing new Date() - past_date