Is it possible to call a function after a specifc time? - reactjs

For example is it possible to call a function after 2 weeks?
I thought about react and a library like dayjs and some code like this:
const date = Number(dayjs(new Date()).format("DD"))
if (date === date + 14) {
//function
}
I testet it with seconds and realised that i am dumb because everytime i refresh the page it will restart the "timer". Do you have any ideas if it is possible?

As suggested in the comments, you could make a cookie/session storage item containing the date at which you want this to take place. Here is an example using session storage, though a cookie is more preferable:
const nowInTwoWeeks = new Date(Date.now()) // Today's date
nowInTwoWeeks.setDate(nowInTwoWeeks.getDate() + 14) // Add 14 days
sessionStorage.setItem('twoWeeksMark', nowInTwoWeeks)
const now = new Date(Date.now()) // Today's date to use for comparison
if (now >= sessionStorage.getItem('twoWeeksMark')) {
// Do the work
}

Related

What should be onLoad dataset for stock highcharts with multiple lines

In the given example, I have two lines to be displayed and datasets/time series data records for them are here dataset1: mock-data/i.js & dataset2: mock-data/iv.
Time range is between 2015 to 2021 years. In each data set there are around 60K to 70K records.
In reality it would be millions of records in each dataset and there will be multiple dataset/lines(40 to 60 datasets/lines).
Question: 1The part which I don't understand is, when I load the chart for the first time, which data should I display ??????? (as there are many records in the dataset)
I checked highcharts example: https://www.highcharts.com/demo/stock/lazy-loading and I feel like, from given time range, it shows each month's first date data when being loaded for the first time.
function getInitialDataPointsFromBackEnd() {
const onLoadDataset = [];
let timestamp;
for (let i = 0; i < dataset.length; i++) {
const { name, datapoints } = dataset[i];
const tempDataset = { name: name, datapoints: [] };
for (let j = 0; j < datapoints.length; j++) {
// push 0th record blindly to onLoadDataset
if (j === 0) {
tempDataset.datapoints.push(datapoints[j]);
timestamp = datapoints[j][0];
timestamp = timestamp + 2.628e9; // timestamp with one month difference
}
// push last record blindly to onLoadDataset
if (j === datapoints.length - 1) {
tempDataset.datapoints.push(datapoints[j]);
onLoadDataset.push(tempDataset);
}
// start finding next month timestamp record
const filteredMonthlyRecord = datapoints.find(
(x) => x[0] === timestamp
);
if (filteredMonthlyRecord) {
// if record is found increse time stamp by one month
timestamp = timestamp + 2.628e9; // timestamp with one month difference
tempDataset.datapoints.push(datapoints[j]);
}
}
}
return onLoadDataset;
}
So I'm trying to apply the similar kind of logic using getInitialDataPointsFromBackEnd function. Assume this is BE functionality or BE implementation in reality but just to make example more understandable I'm using in FE side, which should extract out each month's first record for given range(In my case time range is from 2011 to 2021).
But, since, in each dataset, there are around 60K to 70K records, I have to loop through all of them and prepare my first-load data.
This is very time consuming process. If I have 60 to 70 datasets and from each dataset If I have to extract out each month record, it will take forever to serve the data to front-end.
I'm sure, I'm missing something or making some basic mistakes.
Please help me understand what should be the onLoad dataset if you have two time series datasets as shown below.
My efforts: https://stackblitz.com/edit/js-srglig?file=index.js
Question 2: Also, bottom navigator keeps on updating every time when you try to change the selection and redraws lines in wrong way. How can I fix it too ? Ideally it should not update lining part only scroll trasparent window should be updated. isn't it?

React siblings 'listen' to state change of each other

I am trying to create a birth date validation. I have three selects: year, month, day. All part of a parent Form. So, if the selected year is startYear, then month can be only <= current month. Similar logic should exist for the day.
As I understand, I have to pass selected from child to parent, and then from parent to another child. But I am new to react and I get lost in this logic.
My birthMonth component should be able to console.log the selected year basically. From there on I can manage.
Here is the sandbox: sandbox
I was able to find that out. I'd need to manage state in a parent, in my case it's Form.js:
// Validations for birth date selects
const today = new Date().toJSON().slice(0,10).split('-')
const years = []
const yearNow = Number(today[0])
const startYear = (yearNow - 18)
const endYear = (startYear - 60)
for (let name = startYear; name >= endYear; name--) {
years.push({name});
}
const [selectedYear, setSelected] = useState(years[0])
And then pass this all to a child and the selected state to the sibling:
< SelectBirthYear startYear={startYear} endYear={endYear} years={years} value={selectedYear} onChange={setSelected}/>
< SelectBirthMonth today={today} startYear={startYear} selectedYear={selectedYear}/>
If there is a better cleaner way, please share.

Implementing a 15 minute timeout in React issues

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()

SetDate() behaves weirdly in datepicker modal

I have a day picker in a datepicker modal I am writing in React with hooks. I want to display today's date in the middle and count backwards going up and forwards going down from today. I also need my dates to wrap to the next or previous month and start or end on the correct number of days. My html looks like this
<div className={'dateField'} ref={dayRef}>
<div>{getDayNumber(-3)}</div>
<div>{getDayNumber(-2)}</div>
<div>{getDayNumber(-1)}</div>
{/* TODAY */}
<div>{date.getDate()}</div>
{/* END TODAY */}
<div>{getDayNumber(1)}</div>
<div>{getDayNumber(2)}</div>
<div>{getDayNumber(3)}</div>
</div>
I have a getDayNumber function, but it behaves very strangely. It will count backwards, but not forwards, and sets today's date minus 1 as the same as today's date. I think this is because it is somehow switching to a 0 index count of days? How do I change this back into the day number?
const getDayNumber = (dayNumber) => {
var newDate = new Date(date.setDate(date.getDate() - dayNumber));
console.log('NEW DATE NUMBER!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!', newDate.getDate());
return newDate.getDate();
};
I also have an issue where passing different numbers into getDayNumber() doesn't work - I think this is because I am resetting the central date object with setDate()?:
const [ date, setMyDate ] = useState(new Date());
I think setting the getDayNumber function to create a new Date first gets rid of the problem:
const getDayNumber = (dayNumber) => {
var newDate = new Date();
newDate.setDate(date.getDate() - dayNumber);
console.log('NEW DATE NUMBER!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!', newDate.getDate());
return newDate.getDate();
};

How to make a command time counter

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

Resources