Im making a digital clock for my webpage. But every time i enter the page, it takes 1 second before the string with the current time appears. Is there any way to change that and make it faster so it is not that notisable for the user? Thank you
My js code:
const add_zero = (number) => {
return number < 10 ? `0${number}` : number;
}
const show_current_time = () => {
setInterval(() => {
const today = new Date();
const month = today.getMonth() + 1;
const year = today.getFullYear();
const date = today.getDate();
const hours = add_zero(today.getHours());
const minutes = add_zero(today.getMinutes());
const current_date = `${date}/${month}/${year} ${hours}:${minutes} |`;
document.getElementById("show_current_time").innerHTML = current_date;
}, 1000)
}
window.onload = show_current_time;
You can try calling a function that does the work once, and only then do the setInterval() for that function.
set_current_time()
setInterval(set_current_time, 1000);
It "takes 1 second before the string with the current time appears", because the function show_current_time has setInterval and the last argument is 1000 (1 second).
The function is doing more than what its name suggests: showing the current time. It's also updating it each second. It starts the first update after the document is loaded.
Remove setInterval:
const show_current_time = () => {
const today = new Date();
const month = today.getMonth() + 1;
const year = today.getFullYear();
const date = today.getDate();
const hours = add_zero(today.getHours());
const minutes = add_zero(today.getMinutes());
const current_date = `${date}/${month}/${year} ${hours}:${minutes} |`;
document.getElementById("show_current_time").innerHTML = current_date;
}
If you add show_current_time();, it will call the function sooner.
Calling setInterval(show_current_time, 1000); updates it each second.
window.addEventListener(
'load',
() => {
show_current_time();
setInterval(show_current_time, 1000);
}
);
I avoid using window.load because you lose everything you did with it when you change it.
There might be a gap between the beginning of the document being loaded, and the functions being called. But, depending on the script size how, and how it's loaded, probably it's not noticeable.
use requestAnimation frame, on a recursive loop:
https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
const show_current_time = () => {
const today = new Date();
const month = today.getMonth() + 1;
const year = today.getFullYear();
const date = today.getDate();
const hours = add_zero(today.getHours());
const minutes = add_zero(today.getMinutes());
const current_date = `${date}/${month}/${year} ${hours}:${minutes} |`;
document.getElementById("show_current_time").innerHTML = current_date;
}
show_current_time()
setInterval(show_current_time,1000)
Related
This is my code
I get all the info I need but it only updates itself when I refresh the window I want it to update automatically every second
<script>
const d = new Date();
let date = d.getDate()
let month = d.getMonth();
let year = d.getFullYear();
let hour = d.getHours();
let minute = d.getMinutes();
let second = d.getSeconds();
</script>
<main>
<div class="hero min-h-screen bg-base-200">
<div class="hero-content text-center">
<div class="max-w-md">
<h1 class="text-8xl font-bold">{date}/{month}/{year}</h1>
<br>
<h1 class="text-8xl font-bold">{hour}:{minute}:{second}</h1>
</div>
</div>
</div>
</main>
You would have to re-assign the variables periodically, e.g. using setInterval, using a new Date each time. Note, that if you use exactly one second as an interval, changes could be missed due to shift/slight delays.
Implementing an accurate and efficient timer is an interesting problem of its own, there is an entire HTTP 203 episode on that. Jake's implementation is this (made signal optional):
export function animationInterval(ms, signal, callback) {
// Prefer currentTime, as it'll better sync animtions queued in the
// same frame, but if it isn't supported, performance.now() is fine.
const start = document.timeline ? document.timeline.currentTime : performance.now();
function frame(time) {
if (signal?.aborted) return;
callback(time);
scheduleFrame(time);
}
function scheduleFrame(time) {
const elapsed = time - start;
const roundedElapsed = Math.round(elapsed / ms) * ms;
const targetNext = start + roundedElapsed + ms;
const delay = targetNext - performance.now();
setTimeout(() => requestAnimationFrame(frame), delay);
}
scheduleFrame(start);
}
So it could be used like this:
<script>
import { animationInterval } from './animation.js';
let date, month, year, hour, minute, second;
function update() {
const d = new Date();
date = d.getDate()
month = d.getMonth();
year = d.getFullYear();
hour = d.getHours();
minute = d.getMinutes();
second = d.getSeconds();
}
update();
animationInterval(1000, undefined, update);
</script>
<h1 class="text-8xl font-bold">{date}/{month}/{year}</h1> <br>
<h1 class="text-8xl font-bold">{hour}:{minute}:{second}</h1>
REPL
You can use setInterval to execute code. For example, if you want the code to re-execute every 1 second.
function printTime() {
const date = new Date();
console.log( date.toString() );
}
// function time (in ms)
setInterval(printTime(), 1000);
(Note; StackOverflow's code snippet will only execute setInterval once.)
In my javascript project, I want to check if the time difference is less than 1 second. I use moment to get this difference. This is the function I have written to achieve it.
const withinOneSecond = (time) => {
const currentTime = moment();
return time + 1000 < currentTime;
};
But this doesn't work as expected. How can I check if the given time is within a second to the current time?
You can use moment#diff.
As an example, I've added a second to a date and taking the difference in with .diff passing seconds as second argument should return the difference in seconds
var a = moment();
var b = moment().add(1, 'seconds');
console.log(b.diff(a, 'seconds'))
<script src="https://momentjs.com/downloads/moment.js"></script>
The supported measurements are years, months, weeks, days, hours, minutes, and seconds. Here
For your particular case, you should be doing something like
const withinOneSecond = (time) => {
const currentTime = moment();
return currentTime.diff(time, 'seconds') == 1
};
var time = moment().add(1, 'seconds');
let results = withinOneSecond(time);
console.log(results);
<script src="https://momentjs.com/downloads/moment.js"></script>
You dont need moment for this. Use vanilla, use .getTime() to get time in milliseconds and compare it with the current time. See the code below:
var date = new Date();
const withinOneSecond = (time) => new Date().getTime() - new Date(time).getTime() < 1000;
setTimeout(() => {
console.log(withinOneSecond(date)); // true
}, 500)
setTimeout(() => {
console.log(withinOneSecond(date)); // false
}, 1500)
You just need to use the duration.asHours() method (see the docs).
const withinOneSecond = (time) => {
const currentTime = moment();
return moment.duration(currentTime.diff(time)).asSeconds() > 1;
};
How to convert days to get the hours, minutes and seconds using momentjs? I think my calculation is wrong because I'm getting the difference of date today and date that I'm getting from the API which has 5days.
So far this is my code
const countdown = () => {
let dueDate = '2019-12-04 12:50:42 AM'; //getting this value from the API
let eventTime = moment(dateDue).unix();
let currentTime = moment(new Date()).unix();
let diffTime = eventTime - currentTime;
const interval = 1000;
let duration = moment.duration(diffTime * interval, 'milliseconds');
duration = moment.duration(duration - interval, 'milliseconds');
countDowntimer[dateDue] = setInterval(() => {
setMinutes(duration.minutes());
setSeconds(duration.seconds());
}, interval);
return `${duration.hours()}hr ${duration.minutes()}m ${duration.seconds()}s`;
};
const timer = countdown(minutes, seconds);
return timer;
First of all NEVER subtract from the final date while making a countdown timer, instead calculate the difference at each iteration.
Then for calculate each duration you need to take as value the integer part of the duration and then with the decimal part calculate the next interval multiplied by X ( where x are seconds to make a minute, minute to make an hour and so on).
const time = document.getElementById("time");
const countdown = () => {
let dueDate = '2019-12-04 12:50:42 AM'; //getting this value from the API
let eventTime = moment(dueDate, 'YYYY-MM-DD HH:mm:ss a');
const interval = 1000;
setInterval(() => {
const hours = moment.duration(eventTime - moment()).asHours();
const hInt = Math.floor(hours);
const minutes = moment.duration(60 * (hours - hInt), 'minutes').asMinutes();
const mInt = Math.floor(minutes);
const seconds = moment.duration(60 * (minutes - mInt), 'seconds').asSeconds();
const sInt = Math.floor(seconds);
time.innerHTML = `${hInt}hr ${mInt}m ${sInt}s`;
// set react state here
}, interval);
};
countdown();
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
<span id="time"></span>
Using moment-duration-format
const countdown = () => {
let dueDate = '2019-12-04 12:50:42 AM';
let end = moment(dueDate, 'YYYY-MM-DD hh:mm:ss A');
let start = moment();
const interval = 1000;
setInterval(() => {
start = moment()
let diff = end.diff(start)
document.body.innerHTML = moment.duration(diff).format("HH[hr] mm[m] ss[s]");
}, interval);
}
countdown()
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.js" integrity="sha256-H9jAz//QLkDOy/nzE9G4aYijQtkLt9FvGmdUTwBk6gs=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-duration-format/2.3.2/moment-duration-format.min.js" integrity="sha256-M2KULKSJyw+G0068JiMlM9GX4XpLdUButSzBqntKDZM=" crossorigin="anonymous"></script>
I've got the following code, which is supposed to find the difference in milliseconds from one date, to another. It's meant to get the elapsed time since a view has been opened:
this.timer.start = new Date();
this.timer.intervalRef = setInterval(() => {
this.timer.elapsedTime = moment(new Date()).diff(this.timer.start)
}, 1000);
Then, in the template, it's shown as this:
{{ timer?.elapsedTime | date: 'hh:mm:ss' }}
It should display something like:
00:00:01
00:00:02
00:00:03
...
And the minutes and seconds part, work well. But the "hours" part, is starting always with 1, therefore giving me this output:
01:00:01
01:00:02
01:00:03
...
Can someone explain me what I've got wrong, and why it's working like this?
moment.diff return a duration and not a Date object.
You can use .duration and format with the desired output.
this.timer = {};
let start = moment(new Date());
let intervalRef = setInterval(() => {
let elapsedTime = moment(new Date()).diff(start)
let time = moment.duration(elapsedTime)
let hrs = ('0' + time.hours()).slice(-2);
let mins = ('0' + time.minutes()).slice(-2);
let secs = ('0' + time.seconds()).slice(-2);
this.timer.elapsedTime = `${hrs}:${mins}:${secs}`
console.log(this.timer.elapsedTime)
}, 1000);
<script src="https://momentjs.com/downloads/moment.js"></script>
At present I can only divide the day into 1 hour blocks.
But I need the ranges in 15 minute steps.
Moment-Range Documentation
This is my present code:
function iterateOverDayByIntervalOfHours(inputJSON){
var day = getDayFromFromJSON(inputJSON);
var start = new Date("2016-05-04T00:00:00.000Z");
var end = new Date("2016-05-04T23:59:59.999Z");
var range = moment.range(start, end);
var slices = {}
range.by( 'hours', function(moment) {
console.log(moment);
slices["moment"] = moment
console.log("slices: "+ slices["moment"]);
var ROTsAccumulatedForInterval = getAccumulatedROTForTimeIntervall(range);
var NumberOfFlightsForInterval = getNumberOfFlightsForTimeIntervall(range);
});
console.log(slices["moment"]);
}
any ideas?
Here is another way using moment lib with moment-range extension:
const day_start = moment().startOf('day').hours(7); // 7 am
const day_end = moment().startOf('day').hours(22) // 10 pm
const day = moment.range(day_start, day_end)
const time_slots = Array.from(day.by('minutes', {step: 30}))
in
Array.from(day.by('minutes', {step: 30}))
You can change 'minutes' for hours, days, weeks
and step for how many minutes/hours/days you want to chunk by.
return value will be
[ moment("2017-10-20T07:00:00.000"),
moment("2017-10-20T07:30:00.000"),
moment("2017-10-20T08:00:00.000"),
moment("2017-10-20T08:30:00.000"),
moment("2017-10-20T09:00:00.000"),
moment("2017-10-20T09:30:00.000"),
...
moment("2017-10-20T19:30:00.000"),
moment("2017-10-20T20:00:00.000"),
moment("2017-10-20T20:30:00.000"),
moment("2017-10-20T21:00:00.000"),
moment("2017-10-20T21:30:00.000"),
moment("2017-10-20T22:00:00.000") ]
This doesn't use moment and it's not implemented in your function yet, but this is how I would try to get an object of 15min-chunks. I hope, this is what you are looking for.
var start = new Date("2016-05-04T00:00:00.000Z");
var end = new Date("2016-05-04T23:59:59.999Z");
var slices = {};
var count = 0;
var moment;
while (end >= start) {
start = new Date(start.getTime() + (15 * 60 * 1000));
slices[count] = start;
count++;
}
console.log(slices);
You can also use something like this.
// Take a starting point
const start = moment('00:00:00', 'HH:mm:ss');
// Take a end point
const end = moment('23:59:59', 'HH:mm:ss');
const timeSeries = [];
while (start.isSameOrBefore(end)) {
// add 15 minutes to the starting point
timeSeries.push(start.add(15, 'm').format('HH:mm'));
}
console.log(timeSeries);
Too late but might be helpful, I'm doing the following to divide a day into hour date ranges.
using lodash and moment
const generateDayHours = (x = 24) => {
const hoursArr = [];
_.times(x, (i) => {
hoursArr.push({
fromDate: moment().startOf('day').add(x - (i + 1), 'hour').startOf('hour'),
toDate: moment().startOf('day').add(x - (i + 1), 'hour').endOf('hour')
});
});
return hoursArr;
};
jsbin to test