Checking if date has changed with React/Redux + Moment.JS - javascript

I have a React+Redux application, and I display the date in it using Moment.js. I want a function to run when the date changes.
Right now I have a function to check the date:
checkDate(local) {
if (local === null) {
localStorage.setItem('date', moment().format('MM-DD-YYYY'));
} else if (moment(local).isBefore(moment().format('MM-DD-YYYY'))) {
this.props.resetAll(); // This calls an action.
}
}
And if I call it manually, or refresh the page when the date changes, it works just fine. But, I want to be able to have my application run that this.props.resetAll() line on its own without my having to refresh the page. What would the best way be to go about it? Should it be something that happens on the Redux side of things in an action or reducer? Should I have checkDate() be called every X seconds or so somewhere in the component lifecycle (if so, where)?
Thanks in advance for any help!

I would set a timeout until 24:00 which then calls the update function:
moment() is defined as the current date/time, to get the difference to a specific time, you can use the .diff() function. So for example if you want the milliseconds till the start of the next day:
var msTillEndOfDay = moment().endOf('day').add(1, 'seconds').diff(moment(), 'milliseconds');
.endOf('day') would be 23:59:59 so you just add 1 seconds to have the next day.
You then simply set the Timeout with the specific update function or dispatch the right action:
setTimeout( () => {
this.props.dispatch({type: 'UPDATE_DATE'})
}, msTillEndOfDay);

Related

vue.js clock doesn't refresh when i use setInterval

Im creating a simple vue.js clock, thats why im really confused why it doesn't work.
I tried to implement multiple solutions i found online, but every one of them failed to solve this problem.
App was initialized with npm init vue#latest. Im using the composition API.
Here's my js:
import {
reactive,
computed,
onMounted,
onBeforeUnmount
} from 'vue';
const data = reactive({
date: '',
time: ''
});
const today = new Date();
const getCurrentTime = () => {
const hours = today.getHours();
const minutes = today.getMinutes();
const seconds = today.getSeconds();
const zeroPadding = (num) => {
if (num < 10) {
return `0${num}`
} else {
return num;
}
};
data.time = `${zeroPadding(hours)}:${zeroPadding(minutes)}:${zeroPadding(seconds)}`;
}
onMounted(() => {
setInterval(getCurrentTime, 1000);
});
And here's the html:
<div class="time">
<time class="time__date">{{ data.date }}</time>
<time class="time__hour">{{ data.time}}</time>
</div>
I even copied this solution https://dev.to/snehalkadwe/digital-clock-using-vue-3-composition-api-5cmc, but it also isn't updating the clock. I've had enough, this is my first post on stackoverflow, so yeah, it's a big deal.
#dystrykt9 Here is the working example.
https://codesandbox.io/s/digital-clock-forked-32xmoh
The problem is today variable is constant (by constant i mean value not the const). It is set once and in the setInterval look the once set today variable each time there is same time(hour, minute and second). The reactive data.time value is same each time. But what we need is the today variable needs to get updated with latest time i.e. hour, minute and second.
I also do not get the point of data.date. May be you can use ref or single property or may be you are using that for different logic but is not present in the question code snippet.
The solution would be put the total variable in the setInterval so that every time the variable is set to latest time (hour, minute and second).
For better knowing the problem I have console.log in setInterval callback function. You can check by with setting today outside the callback and inside the callback.

How to run a timer on server side

I would like to have a countdown timer always show a countdown for every new user. Basically, if I close the webpage, and reopen it, the timer should still be running. I'm thinking of using the JS variable code functions to define a new client's timezone together with an if statement comment and make it a repeat loop?
Basically, I would want to run a timer on the server side, not the client side.
Has anyone done this before?
Sounds something that you could try to solve with browsers localStorage. If your only requirement is to keep saved time available after you close tab/browser and come back to your page, this is a good fit for you.
Here's a small Codesandbox example code of how to conditionally check and save to localStorage and then start counter based on that value.
https://codesandbox.io/s/4xw97q02m0
EDIT: same code pasted to a post
function setCurrentTime(){
let localStore = window.localStorage.getItem("myTime") // Check if already exists
if(localStore) return localStore
const time = Date.now(); // get current time stamp
window.localStorage.setItem("myTime", time) // Save to localStorage
return time
}
function startCount(){
const time = setCurrentTime()
const elem = document.getElementById("app")
setInterval(() => {
elem.innerHTML = `seconds since time saved:
${Math.floor((Date.now() - time) / 1000)}
`
}, 1000)
}
startCount()
<div id="app"></div>

User scheduled jobs

I would like to allow my users set a schedule when they would like a particular action to occur. I use a node server on azure. I am currently looking at node-schedule and would be making use of it. What I am contemplating is running a master schedule every hour that checks the database for user specified schedules and this schedule sets a new schedule based on the schedules from users. But I don't know if this is a good practice, plus I'm concerned about the server load.
You can use node's cron for that, and accommodate in different ways.
The pseudocode below gives a general idea.
var CronJob = require('cron').CronJob;
new CronJob('0 0 * * * *', function () { // every hour
// check schedules planned for the future, stored as ISODate
DB.getUserSchedule({jobdate:{$gte:Date.now()},
function(userSchedules) {
userSchedules.forEach(sched) {
// convert the date back to a string parsed by cron
var d=extractDayHourMin(sched)
var jobtime = d[4] +' '+d[3]+' '+d[2]+' '+d[1]+' '+d[0]
// setup a new job
var job=new CronJob(jobtime, function() {
performUserJob()
job.stop(); // fires only once
DB.removeUserSchedule(userSchedule);
})});
see https://github.com/ncb000gt/node-cron
However, this is possibly not the best solution : this does creates as much process as schedule, so yes, it would consume more resources than required. Instead of scheduling the schedulers, depending on the granularity of the possible calendar (hour, 1/2 hour, 1/4h), you could also query the db every hour (or 30 or 15mn) to retrieve every date that met, and trigger the appropriate function.
Search Quartz schedule.
My project using that to set the time to send email.

How to execute a function only once in a day(&only if the app is opened)?

Let i have a function
function alert(){
alert("notification")
}
this function is a part of a mobile app, i want to show this alert(execute function) only once in a day only if user opens the app,
if user didn't open the app for so many days it shouldn't execute that function for that much days.
How to implement in javascript?
can anyone provide a common logic that can be used every where even in ios or ionic...etc ?
Select somewhere that you can store persistent data. That will depend on whatever APIs the app supplies.
Use new Date() to find out the current time.
Compare that to the stored time the function last executed fully. If it is less than a day, return immediately.
Otherwise, store the new time and let the rest of the function run.

Auto update timeAgo value from submitted date

EDIT: I think I should make things more obvious.
What I am trying to do is to make the function that displays the "time ago" from the submitted date of the post auto refresh every minute so that it stays relatively accurate even if the template is not re rendered.
I'd like to auto update my timeago value in my template but it is not working.
I've tried to set up my code with a reactive function, based on the answer to a similar question (https://stackoverflow.com/a/17933506)
Here's my code:
var timeAgoDep = new Deps.Dependency(); // !!!
var timeAgo;
var timeAgoInterval;
Template.postItem.created = function() {
function getTimeago() {
//var now = new Date();
timeAgo = moment(this.submitted).twitter();
timeAgoDep.changed(); // !!!
};
getTimeago(); /* Call it once so that we'll have an initial value */
timeAgoInterval = Meteor.setInterval(getTimeago, 5000);
};
Template.postItem.posted = function() {
timeAgoDep.depend(); // !!!
return timeAgo;
};
Template.postItem.destroyed = function() {
Meteor.clearInterval(timeAgoInterval);
};
I'm pretty sure that the problem comes from this.submitted because if I assign timeAgo = now for example, it will display the time and update like it's supposed to.
I also know that moment(this.submitted).twitter() works fine because when all I do is return it through a helper, it works.
A much better way to do this is to just embrace Meteor's reactivity and render time-dependent values reactively. In your case, the problem is that you are invalidating the dependency once every 5 seconds for each postItem rendered, which will quickly turn into a huge mess.
See https://github.com/mizzao/meteor-timesync for a package that provides reactive time variables on the client (and they are synced to server time too!) It's basically doing what you want, but in a cleaner way. (Disclaimer: I wrote this package.)
You can use moment in the same way to compute the actual string to display. For example, get rid of all the other stuff and just use
Template.postItem.posted = function() {
return moment(this.submitted).from(TimeSync.serverTime());
}
The moment().twitter() extension doesn't seem like a good choice because it only uses the current client time and doesn't allow you to pass in a specific (i.e. server-synced) time or reactive value.

Categories