How to convert a string to time in javascript - javascript

I'm trying to create a countdowntimer in Javascript. There are a lof of examples on the internet. I'm trying to adjust these to my own needs. I want a countdown timer that, when started, countsdown to the whole hour. For example, if I run the code at 13:15 it wil count down to 14:00.
The problem I have is getting the time to countdown to.
var cd = new Date("Jan 5, 2021 15:37:25").getTime();
In the above example you have a defined date. I'm trying to change this to a time to the first upcoming hour. Below is what I have:
var countdowndate = newDate("cd.getMonth, cd.getYear (cd.getHour + 1):00:00").getTime();
This isn't working. What am I doing wrong here? Any help is appreciated.

Here's a very expressive way of solving this:
Get the current time stamp, floored to the last full minute.
Get how many full minutes remain until the next hour, transform to milliseconds.
Sum up the results of 1 and 2.
function getBeginningOfNextHour() {
const msPerMinute = 60 * 1000;
const currentDate = new Date();
const currentDateTimestampRoundedToMinute = Math.floor(+currentDate / msPerMinute) * msPerMinute;
const msUntilNextHour = (60 - currentDate.getMinutes()) * msPerMinute;
return new Date(currentDateTimestampRoundedToMinute + msUntilNextHour);
}
console.log(getBeginningOfNextHour());

Related

How to get future date based on timestamp ratio

I am trying to have a virtual calendar for a game.
I have events that will last a certain time in reality (1 week, 1 month).
In the game those events should always be equal to 1 year.
To make things simple my goal was to use date-fns and work with timestamps to keep a ratio.
Lets say I have an event running for 1 week (real life)
In game that would be 1 year.
If I try to get the in-game date when I'm at event start + 3 days (almost half of the event passed). Theoretically I should be close to 6 months in the virtual calendar however while testing its gives me an answer years later.
import {
addDays,
addYears,
getTime
} from "date-fns";
// Initiate Dates
const now = new Date()
const nextWeek = addDays(now, 7);
const nextYear = addYears(now, 1);
// Initiate Timestamp convertions
const currentTimestamp = getTime(now)
const tmrTimestamp = getTime(addDays(now, 3))
const nextWeekTimestamp = getTime(nextWeek)
// Calculate differences
const differenceReal = nextWeekTimestamp - currentTimestamp
const differenceVirtual = getTime(nextYear) - currentTimestamp
console.log(`difference_real : ${differenceReal}`)
console.log(`difference_virtual : ${differenceVirtual}`)
// Calculate the ratio
const ratio = differenceReal / differenceVirtual
// Log information
console.log(`ratio: ${ratio}`)
console.log(`ts_now ${getTime(now)}`)
console.log(`ts_tmr ${getTime(tmrTimestamp)}`)
//Calculate equivalence of day+1 on a year
const nextDayRatioed = tmrTimestamp / ratio
console.log(`ts_ratioed: ${Math.round(nextDayRatioed)}`)
console.log(`ts_next_year: ${getTime(nextYear)}`)
console.log(`next_year: ${nextYear.toLocaleString()}`)
console.log(`tmr_relative: ${new Date(Math.round(nextDayRatioed)).toLocaleString()}`)
Output:
How could I get the tmr_relative to be the correct value which would be more or less January of 2022
You must keep as constant
the start time of your game as the point of origin.
the ratio that you want for time. In your case 1 week is 1 year for your game.
Check the following way to achieve that using only date.
const ratio = 365/7; //This is the virtual ration that you want
const nowReal = new Date() //This would always be the basis to compare
//Use a fixed date one week later to test how it would behave
const nextWeekReal = new Date();
nextWeekReal.setDate(nextWeekReal.getDate() + 7);
//Use a fixed date 2 week later to test how it would behave
const doubleNextWeekReal = new Date();
doubleNextWeekReal.setDate(doubleNextWeekReal.getDate() + 14);
//Check the next week virtual date
console.log(virtualDate(nowReal, datediff(nowReal, nextWeekReal), ratio));
//Check after 2 weeks the virtual date
console.log(virtualDate(nowReal, datediff(nowReal, doubleNextWeekReal), ratio));
function datediff(first: any, second: any) {
// Take the difference between the dates and divide by milliseconds per day.
// Round to nearest whole number to deal with DST.
return Math.round((second-first)/(1000*60*60*24));
}
function virtualDate(basis: Date, diff: number, ration: number){
const virtualDate = new Date();
virtualDate.setDate(basis.getDate() + diff * ratio);
return virtualDate;
}
Result considering that you start the game now on 24/7/21.
After 1 week have passed in real time it will print you 1 year later from the point of origin
After 2 weeks have passed in real time it will print you 2 years later from the point of origin
Lets say I have an event running for 1 week (real life) In game that
would be 1 year. If I try to get the in-game date when I'm at event
start + 3 days (almost half of the event passed). Theoretically I
should be close to 6 months
//Use a fixed date half a week later to test how it would behave
const halfWeekReal = new Date();
halfWeekReal.setDate(halfWeekReal.getDate() + 3);
console.log("Half Week have passed in real time " + halfWeekReal);
//Check after half week the virtual date
console.log("Virtual date will be " + virtualDate(nowReal,
datediff(nowReal, halfWeekReal), ratio));
This will print
It is about 5 months, which is the correct behavior you have described.
Here's a solution using plain old vanilla JS.
let refInGameDate = new Date()
document.querySelector('#days').addEventListener('change', e => {
let days = +e.target.value
let years = (Math.floor(days / 7) + (days % 7 / 7)).toFixed(2)
document.querySelector('#ingame').innerText = years
let rd = refInGameDate.getTime() + (years * 365 * 24 * 60 * 60 * 1000)
document.querySelector('#indate').innerText = new Date(rd).toString();
})
<input type='number' id='days' /> real-time days
<hr>
<div>in-game translation: <span id='ingame'></span> years</div>
<div>date representation: <span id='indate'></span></div>

How to make a time* range include upper bound

I've divided a day into 8 ticks of three hours each. When making this range it goes from 00:00 to 21:00, and not until 00:00 again.
const startDate = new Date("2021-03-14T23:00:00.000Z");
const endDate = new Date("2021-03-15T23:00:00.000Z");
const dayInThreeHourPeriods = d3.timeHour.every(3).range(startDate, endDate);
dayInThreeHourPeriods.forEach((period) => {
console.log(`period: ${format(period, 'HH:mm')}`);
});
// outputs
// from: 00:00
// to: 21:00
// would like it to go to 24:00
How can I change this so that it goes to 24:00?
I want to use it for an axis:
Made a working example here: https://jsfiddle.net/Spindle/kfL5oh12/21/
This is intended from the .range method, as d3.timeHour.every is just an alias to interval.range;
From d3-time docs:
interval.range(start, stop[, step]) ยท Source
Returns an array of dates representing every interval boundary after or equal to start (inclusive) and before stop (exclusive). If step is specified, then every stepth boundary will be returned; for example, for the d3.timeDay interval a step of 2 will return every other day. If step is not an integer, it is floored.
As you've already stated in your own answer, it seems like a known issue.
Anyway, why don't use write your own logic to divide the day into 3-hours chunks? This way we don't need to rely on d3d3's .range method;
let startDate = new Date("2021-03-14T23:00:00.000Z");
let endDate = new Date("2021-03-15T23:00:00.000Z");
var dayInThreeHourPeriods = [ startDate ];
while (endDate > startDate) {
startDate = new Date(startDate.getTime() + (60 * 60 * 3 * 1000));
dayInThreeHourPeriods.push(startDate);
}
console.log(dayInThreeHourPeriods);
Updated JSFiddle
Turns out this is a known issue.
What people tend to do is add a small time period and suddenly it's inclusive:
d3.range(min, max+0.001)
or in my case:
const dayInThreeHourPeriods = d3.timeHour.every(3).range(startDate, d3.timeHour.offset(endDate, 1));
Not ideal. Look there's a proposal to have 'rangeInclusive' which would be better already. But there is no activity on that issue.
If anyone has a better idea for the time being I'd be interested.

Trying to add a timer to my website to countdown days

I'm trying to get a timer to count down to a date by days and I don't know why this isn't working it just says NaN
function daysUntil24thApril2016() {
var april2016 = new Date(24, 4, 2016);
var difference = april2016.getMilliseconds - Date.now().getMilliseconds;
return difference / 1000 / 60 / 60 / 24;
}
$(document).ready(function() {
console.log("asdasd")
$('#dateTime').text(daysUntil24thApril2016());
});
There are several mistakes you made in your script, I'll try to explain each to help you understand it and finally give you a corrected script the way you wrote it:
new Date() wants the year first, then month - 1 and finally the days. So to get the 24.04.2016, you have to do new Date(2016, 3, 24)
For a Date there is a getMilliseconds function, but it returns the milliseconds part of that date, not the unix timestamp you wanted
.getTime() is the function to get the unix timestamp in milliseconds from this date
Date.now() already returns the unix timestamp (a number), there is no getMilliseconds() for that and therefore it returned undefined
Even if there were a getMilliseconds function, the way you wrote it without the braces () would not have called it anyway but returned the function. They way you wrote it resulted in var difference = function - undefined which is NaN: "Not a number".
Therefore difference was no number in your example (it was Nan) and you cannot do any math with it obviously, it stays NaN
Using Math.floor will give you full days
See below for a version of your script where the points above are corrected.
function daysUntil24thApril2016() {
var april2016 = new Date(2016, 3, 24);
var difference = april2016.getTime() - Date.now();
return Math.floor(difference / 1000 / 60 / 60 / 24);
}
$(document).ready(function() {
$('#dateTime').text(daysUntil24thApril2016());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="dateTime"></div>
Something like this will solve your problem:
function daysUntil24thApril2016() {
var april2016 = new Date("2015-04-24");
var difference = Date.now()-april2016;
return Math.floor((difference) / (1000*60*60*24))
}
$(document).ready(function() {
console.log(daysUntil24thApril2016());
});
When you subtract one Date object from another you will get the time difference in milliseconds. Using Math.floor() will return a whole (integer) number of days.

Setting timezone for running clock in JavaScript

Good days guys. I have this nice and clean code for a running clock.
<script type="text/javascript">
function DisplayTime(){
if (!document.all && !document.getElementById)
return
timeElement=document.getElementById? document.getElementById("curTime"): document.all.tick2
var CurrentDate=new Date()
var hours=CurrentDate.getHours()
var minutes=CurrentDate.getMinutes()
var seconds=CurrentDate.getSeconds()
var DayNight="PM"
if (hours<12) DayNight="AM";
if (hours>12) hours=hours-12;
if (hours==0) hours=12;
if (minutes<=9) minutes="0"+minutes;
if (seconds<=9) seconds="0"+seconds;
var currentTime=hours+":"+minutes+":"+seconds+" "+DayNight;
timeElement.innerHTML="<font style='font-family:Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800&subset=latin,cyrillic-ext,latin-extfont-size:14px;color:#fff;'>"+currentTime+"</b>"
setTimeout("DisplayTime()",1000)
}
window.onload=DisplayTime
</script>
My only problem is it's based the system time. How can I set the timezone so that it will display the correct time based on the timezone specified?
There's nothing built into the JavaScript Date object that handles any timezones other than local (system) time and UTC.
You can do it by giving your Date instance the wrong time, using the delta between one of those timezones (local or UTC) and the time zone you want to use. It's easier if you use UTC.
So for instance, say we want our time in GMT+01:00:
var dt = new Date();
dt.setTime(dt.getTime() + (60 * 60 * 1000));
// ^^^^^^^^^^^^^^---- one hour in milliseconds,
// which is our offset from UTC/GMT
var hours = dt.getUTCHours(); // Use UTC methods to get time
var minutes = dt.getUTCMinutes();
var seconds = dt.getUTCSeconds();
Time stuff, particularly with timezones, is hard. You might look at using a library for it, although for just this sort of clock that would be overkill. One good library is MomentJS (which has a timezone add-on).
You can use getTimezoneOffset method of the Date object. It gives you the timezone offset, according to your timezone in minutes.
So in order to get the current time in UTC (+0 timezone) you can do something of the sort:
var tzOffset = CurrentDate.getTimezoneOffset();
// some timezones are not set hours, so we must calculate the minutes
var minutesOffset = parseInt(tzOffset%60,10);
// the offset hours for the timezone
var hoursOffset = parseInt(tzOffset/60, 10);
Then you need to do some math in your code to account for the offset:
var hours = CurrentDate.getHours() + hoursOffset;
var minutes = CurrentDate.getMinutes() + minutesOffset;
This would account for your timezone. If you want to calculate another timezone, that you specify, change the tzOffset above to show your timezone.
var tzOffset = CurrentDate.getTimezoneOffset() + TIMEZONE_HOURS*60;
TIMEZONE_HOURS is the timezone in hours you want, e.g. if you want UTC+3, you must set TIMEZONE_HOURS to 3.
As a whole timezones are a bit complicated task because they change a lot and there are some caveats with them. If you want to dwell more into this, check this answer in another question on SO
I have implemented your working code by adding one more function to obtain what you want. See this will help
function DisplayTime(timeZoneOffsetminutes){
if (!document.all && !document.getElementById)
return
timeElement=document.getElementById? document.getElementById("curTime"): document.all.tick2
var requiredDate=getTimeZoneTimeObj(timeZoneOffsetminutes)
var hours=requiredDate.h;
var minutes=requiredDate.m;
var seconds=requiredDate.s;
var DayNight="PM";
if (hours<12) DayNight="AM";
if (hours>12) hours=hours-12;
if (hours==0) hours=12;
if (minutes<=9) minutes="0"+minutes;
if (seconds<=9) seconds="0"+seconds;
var currentTime=hours+":"+minutes+":"+seconds+" "+DayNight;
timeElement.innerHTML="<font style='font-family:Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800&subset=latin,cyrillic-ext,latin-extfont-size:14px;color:#fff;'>"+currentTime+"</b>"
setTimeout("DisplayTime(-330)",1000)
}
window.onload=DisplayTime(-330);
function getTimeZoneTimeObj(timeZoneOffsetminutes){
var localdate = new Date()
var timeZoneDate = new Date(localdate.getTime() + ((localdate.getTimezoneOffset()- timeZoneOffsetminutes)*60*1000));
return {'h':timeZoneDate.getHours(),'m':timeZoneDate.getMinutes(),'s':timeZoneDate.getSeconds()};
}
#curTime{
background-color:#000;
}
<div id="curTime"></div>
visit this link as a reference
example:
var x = new Date();
var currentTimeZoneOffsetInHours = x.getTimezoneOffset() / 60;
You can try using moment.js
It is very nice library which handles timezones too.

How to get a countdown timer that starts on a specific date/time and counts down every hour

I'm trying to achieve a countdown timer that would use a specific date and time for it to start. From there I need it to countdown from 1 hour and then update the initial date and time by adding an hour and then repeat itself indefinitely.
This is used for a product auction that would get a new product once one sells out and the price drops every hour from when it is added to the auction which could be any time of day.
Example:
I need this timer to start on 2014, 7, 25, 11, 30, 0, 0 (August 25th,
2014 at 11:30 AM EST) It would countdown 1 hour and upon completion it
would add on an hour to the start date making 2014, 7, 25, 12, 30, 0,
0 This would repeat itself indefinitely until I choose to stop it.
It would also not change based on if the site visitor refreshed the page, meaning they visit the page and see 33 minutes left, not keep resetting it to 1 hour for each refresh.
I was going to use this countdown timer: http://keith-wood.name/countdown.html
What I needed was the time that I give it in variable form. I tried to research this as much as possible without any luck, most are not specific enough or only deal with the date and not the time.
I'm not that well versed in Javascript and jQuery; here is what I had so far.
Pardon my code, there are many ideas at work here:
$(document).ready(function() {
var everyhour = new Date();
//everyhour = new Date(everyhour.getFullYear() + 1, 1 - 1, 1);
everyhour = 2014, 8-1, 25, 9, 30, 0, 0;
// the above was my initial try and it wasn't getting me anywhere
var date = new Date(2014, 7, 25, 12, 0, 0);
var now = new Date();
var diff = date.getTime()/1000 - now.getTime()/1000;
alert (diff);
// The above was another stab at it, got me a little closer
var minutesToAdd = 60;
date.setMinutes(date.getMinutes()+minutesToAdd);
// the above was something I found on this website and got brain block
// the below was me trying to start a loop and get the date to update by adding an hour onto it
// for i
// if diff = 3600 {
// var dated = dated + 1
// }
$('#auctioncountdown').countdown({until: diff, format: 'HMS'});
});
Any help would be greatly appreciated.
You can use setInterval to continuously update the countdown:
setInterval(function(){
// update countdown
}, 1000 * 60); // for every hour
setInterval will cause the function you pass in to run continuously every hour (in this case).
I ended up going with something simpler and ultimately achieving what I was originally asking, using 'now' instead of a specific date. Having a timer reset itself every hour and refreshing the page to changed content. In my case I'm actually adding a couple of minutes to the time because of a background app taking a minute or two to do it's communication on updating the server with new information. It's basically to get rid of the lag time and make a better user experience for the page visitor.
Here is my code:
$(document).ready(function() {
function ShowTime() {
var now = new Date();
var diff = -2;
var nowTwo = new Date(now.getTime() + diff*60000);
var mins = 59-nowTwo.getMinutes();
var secs = 59-nowTwo.getSeconds();
timeLeft = "" +mins+'m '+secs+'s';
$("#auctioncountdown").html(timeLeft);
if ($("#auctioncountdown").html() === "0m 1s") {
location.reload(true)
};
};
function StopTime() {
clearInterval(countdown);
}
ShowTime();
var countdown = setInterval(ShowTime ,1000);
});

Categories

Resources