How to convert ISO string format date time to next hour - javascript

I am using the following function to convert my date in RFC3339. I want it to convert in upper limit.
Can anyone assist me, how do I convert it to upper limit?
const date = new Date();
// RFC 3339 format
const targetTime = date.toISOString();
Current output is:
2022-12-20T05:26:12.968Z
Expected output should be
2022-12-20T06:00:00Z

See this answer, very similar but you can replace Math.round with Math.ceil to round up like you want and in addition you'll need to get the percentage the hour is complete (assuming you don't want to round up exact hours).
const milliSecondsInHour = 60*60*1000;
const roundDateToNextHour = (date: Date) => {
const percentHourComplete = (x.getTime() % milliSecondsInHour) / milliSecondsInHour;
date.setHours(date.getHours() + Math.ceil(percentHourComplete));
date.setMinutes(0, 0, 0); // Resets also seconds and milliseconds
return date;
}

If the intention is to the next full UTC hour, test if UTC minutes, seconds or milliseconds are greater than zero. If any of them are, increment the hour and zero the other values, e.g.:
// If the provided date is not exactly on the UTC hour,
// return a date that is the next full UTC hour after
// the provided date.
function toFullUTCHour(date) {
let d = new Date(+date);
d.setUTCHours(d.getUTCHours() + (d.getUTCMinutes() || d.getUTCSeconds() || d.getUTCMilliseconds? 1 : 0), 0,0,0);
return d;
}
let d = new Date()
console.log(d.toISOString() + '\n' +
toFullUTCHour(d).toISOString());
// Simplified version, only works in general for UTC hour
function ceilUTCHour(date = new Date()) {
let d = new Date(+date);
d.setHours(d.getHours() + (d%3.6e6? 1 : 0), 0, 0, 0);
return d;
}
console.log(ceilUTCHour(d).toISOString());
Since, in ECMAScript, UTC days are always exactly 8.64e7 ms long and hours are always exactly 3.6e6 ms long, you can just get the remainder of the current UTC time value and if it's not zero (which will be almost always) add 1 to the UTC hour, then zero the minutes seconds and milliseconds as for the ceilUTCHour function above.

Related

Given a date, how can I get the previous Monday in UTC format regardless of time zone?

I am given a unix timestamp like this: 1655402413 and am needing to find find the midnight of the Monday (in UTC/GMT format) of the same week, regardless of what day it is or what time zone. I then need to represent that Monday as a unix timestamp and return it. The function I have is as follows:
function findMonday(unixTimeStamp) {
let startDate = new Date(unixTimeStamp);
let startDay = startDate.getDay();
let diff = startDate.getDate() - startDay + (startDay === 0 ? -6 : 1);
let monday = new Date(startDate.setDate(diff));
monday.setHours(0, 0, 0, 0);
monday = new Date(monday).valueOf();
return monday;
}
That function almost works, but there are two problems, both related to the fact that the Date seems to always work with the user's current timezone:
If given a timestamp that evaluates to midnight on a Monday in UTC/GMT format, depending on the time zone of the user, it returns the Monday of the previous week (because startDate evaluates to the Sunday before the Monday), which is not good.
The monday that is returned is in local time, not UTC/GMT time.
This is driving me absolutely insane. Working with dates in JavaScript is a nightmare, and I would appreciate any direction you can give me.
Multiply the unix timestamp by 1000, and use the UTC methods like getUTCDate instead of getDate, setUTCHours instead of setHours etc..
Of course to return as unix time, just divide by 1000.
eg.
function findMonday(unixTimeStamp) {
let startDate = new Date(unixTimeStamp * 1000);
let startDay = startDate.getUTCDay();
let diff = startDate.getUTCDate() - startDay + (startDay === 0 ? -6 : 1);
let monday = new Date(startDate.setUTCDate(diff));
monday.setUTCHours(0, 0, 0, 0);
monday = new Date(monday).valueOf();
return monday;
}
const monday = findMonday(1655402413);
const unixMonday = Math.trunc(monday / 1000);
console.log('The Date: ' + new Date(monday).toISOString());
console.log('Unix time: ' + unixMonday);
As for Keith's answer but a little more concise. It returns seconds, not milliseconds. ;-)
// Given UNIX timestamp, return similar timestamp for
// previous UTC Monday at 00:00:00
let getLastUTCMonday = ts => {
let d = new Date(ts * 1e3);
d.setUTCDate(d.getUTCDate() - (d.getUTCDay() || 7) + 1);
return d.setUTCHours(0,0,0,0) / 1e3 | 0;
};
let ts = 1655402413;
let tsPriorMonday = getLastUTCMonday(ts)
console.log(
`Start date : ${new Date(ts*1e3).toUTCString()}\n` +
`Prior Monday: ${new Date(tsPriorMonday * 1e3).toUTCString()}`
);
In ECMA-262, offsets from the epoch (in milliseconds) are called "time values". A timestamp is anything that represents a time or date, so a time value is a timestamp. ;-)
Given that ECMAScript UTC days are always exactly 8.64e7 milliseconds long, you can work out the previous UTC Monday from today by some simple arithmetic.
The ECMAScript epoch was Thursday, 1 Jan 1970 00:00:00, so you can:
Subtract 4 UTC days worth of milliseconds (34.56e7) from the date to align with Monday instead of Thursday
Get the remainder of dividing that value by the number of milliseconds in 7 UTC days (7 * 8.64e7 or 60.48e7)
Subtract the remainder from the current date, which will return the previous Monday and also remove the time component
The above algorithm only works for dates after the epoch. Dates before then have time values are negative so add 3 days before getting the remainder, then subtract the remainder + 7 days (i.e. date - remainder - 7 days).
The following just does the post–epoch calculation:
let getPreviousUTCMonday = date => {
let weekRem = (date - 34.56e7) % 60.48e7;
return date - weekRem;
}
let d = new Date();
for (let i=0; i<12; i++) {
console.log(`${d.toUTCString()}\n` +
`${new Date(getPreviousUTCMonday(d)).toUTCString()}`);
d.setDate(d.getDate() + 1);
}

How do I find the number of milliseconds until midnight UTC in javascript?

I'm making a Discord bot that I want to have a reward that you can claim once per day, and if you've already claimed it, it tells you how much time left. I've made the function that converts milliseconds into a readable format, but somehow using Date objects isn't working. Here is my code to get the timestamp in ms of the next claim time:
const nextdate = new Date(oldms + 86400000); // oldms is the miliseconds timestamp of the last claim time, this adds 24 hours to it.
// The next two lines are to set it to 00:00:00 so it can show the time until properly.
const regex = new RegExp(" ..:..:.. GMT");
const realnextdate = new Date(nextdate.toUTCString().replace(regex, ""));
return realnextdate.getTime();
But when I run it, the time is always the day before the next claim, so the remaining time is negative. Can anyone tell me how I can get the actual timestamp of the next midnight?
Edit 1: My server is in UTC + 2 timezone, if that changes anything. (Optimally, it should not.)
Adding one day is not as simple as adding 24 hours where daylight saving is observed, see How can I add 1 day to current date?
It's unclear to me whether you want UTC or local midnight, but here is how to get both. For UTC midnight, create a date for 24:00:00 UTC and subtract the current date and time from it.
For local midnight, subtract the date from midnight on the same day. In both cases, the milliseconds can then be formatted as H:mm:ss.sss or whatever suits.
The difference between the time to local midnight and UTC midnight will be equivalent to the current timezone offset.
// Format ms as H:mm:ss.sss
function msToHMS(ms) {
let h = ms / 3.6e6 | 0;
let m = (ms % 3.6e6) / 6e4 | 0;
let s = (ms % 6e4) / 1e3 | 0;
let ss = (ms % 1e3);
return `${h}:${('' + m).padStart(2, '0')}:${('' + s).padStart(2, '0')}.${(''+ss).padStart(3, '0')}`;
}
// Return time to UTC midnight as H:mm:ss.sss
function timeToUTCMidnight(d = new Date()) {
return msToHMS(new Date(d).setUTCHours(24,0,0,0) - d);
}
// Return time to local midngith as H:mm:ss.sss
function timeTolocalMidnight(d = new Date()) {
return msToHMS(new Date(d).setHours(24,0,0,0) - d);
}
console.log('To UTC midnight : ' + timeToUTCMidnight().padStart(12));
console.log('To local midnight: ' + timeTolocalMidnight().padStart(12));
Get time till next midnight
Algorithm
Get next midnight time as a js date object
Get the current time
Subtract, to get remaining time
To get the next midnight, use
function getNextMidnightTime() {
var midnight = new Date()
midnight.setHours(24);
midnight.setMinutes(0);
midnight.setSeconds(0);
midnight.setMilliseconds(0);
return midnight.getTime()
}
For which to get the time remaining till midnight,
function getTimeToMidnightFromNowInMS() {
return getNextMidnight() - new Date().getTime()
}
To test
console.log(getTimeToMidnightFromNowInMS())
You can get the time of the start of the next day and then subtract the current time:
function msTillNextUtcDay() {
const msInDay = 86400000; // 24 * 60 * 60 * 1000
const date = Date.now() // time since midnight on January 1, 1970, UTC (ecmascript epoch)
const msNextDay = Math.ceil(date/msInDay) * msInDay; //gets the time of in ms of the start of the next utc day in ecmascript epoch "format"
return msNextDay - date; //Subtracts current time from start of next day
}
You can use DateInstance.getTimezoneOffset() to get the minutes difference from the Client to UTC. Set your minutes plus the offset, after setting everything else to zero, then DateInstance.getTime() and subtract Date.now().
function msToUTCMidnight(){
const d = new Date, z = d.getTimezoneOffset();
d.setDate(d.getDate()+1); d.setHours(0); d.setSeconds(0);
d.setMilliseconds(0); d.setMinutes(0+z);
return d.getTime()-Date.now();
}
let result = msToUTCMidnight();
console.log(result);
// show Client time at midnight UTC
console.log(new Date(Date.now()+result).toString());

How to round to the nearest date using JavaScript Date Object

How to round to the nearest date using JavaScript Date Object?
I have 2020-10-14T18:10:48.960Z and I want it a function that returns 2020-10-15T05:00:00.000Z which is the closest date in my timezone CST. Or if I give it 2020-10-14T16:10:48.960Z I want it to return 2020-10-14T05:00:00.000Z.
The easiest way I can think of is to just add 12 hours to the date, then truncate the time portion. This has the effect of rounding to the nearest date (anything before noon just has the time truncated, anything after goes to the next day, then has the time truncated).
let d = new Date();
// add 12 hours to the date
d.setTime(d.getTime() + (12*60*60*1000));
// truncate the time
d.setHours(0,0,0,0);
console.log(d);
You can check the hour and if it's before 12, set to the time to 00:00:00. If it's 12 or after, set the time to 24:00:00, e.g.
let d = new Date();
d.setHours(d.getHours() < 12? 0 : 24, 0,0,0);
console.log(d.toISOString() + '\n' + d.toString());
//this code will round to the nearest date
const roundToNearestDay = (date) => {
let isPastNoon = date.getHours() >= 12
if (isPastNoon)
//if first parameter > 23, will increment date +1
date.setHours(24,0,0,0)
else
date.setHours(0,0,0,0)
return date
}
let nearestDay = roundToNearestDay(new Date())
console.log(nearestDay)

Proper way to manipulate date string with wrong year, but correct time

I'm having to hit an API I have no access to fixing and I need to start a timer showing how long someone has been in a queue for. The date I get back is in this format 1556214336.316. The problem is the year always shows up as 1970, but the time is the correct start time. I need to calculate the difference between the time now, and the time the conversation was created at. I have tried this with little success and was wondering if there is an elegant way to only get the difference in time and not the total amount of seconds.
convertDateToTimerFormat = (time) => {
const now = new Date();
const diff = Math.round((now - parseInt(time.toString().replace('.', ''))) / 1000);
const hours = new Date(diff).getHours();
const minutes = new Date(diff).getMinutes();
const seconds = new Date(diff).getSeconds();
return `${hours}:${minutes}:${seconds}`;
}
The weird parseInt(time.toString().replace('.', ''))) seems to fix the 1970 issue, but I still can't get the data to be manipulated how I need.
I tried the momentjs library, but their diff method only appears to allow for days and hours.
Any help/guidance, would be much appreciated.
Edit with working code:
convertDateToTimerFormat = (time) => {
const now = new Date();
// eslint-disable-next-line radix
const diff = new Date(Number(now - parseInt(time.toString().replace(/\./g, ''))));
const hours = diff.getHours();
const minutes = diff.getMinutes();
const seconds = diff.getSeconds();
return `${hours}:${minutes}:${seconds}`;
}
Unix time values are the number of seconds since the Epoch and won't have a decimal like your 1556214336.316
If I take 1556214336 (without the .316) and put it in a converter I get the output 04/25/2019 # 5:45pm (UTC) which is not 1970 — it seems an accurate time (I haven't independently verified)
It seems, then, your 1556214336.316 is the seconds.milliseconds since the epoch.
Javascript uses the same epoch, but is the number of milliseconds since the epoch, not seconds, so if I'm correct about the time you're getting you should be able to just remove the decimal place and use the resulting number string. Indeed
var d = new Date(1556214336316);
console.log('Date is: ' + d.toUTCString());
produces
Date is: Thu, 25 Apr 2019 17:45:36 GMT
which exactly matches the converter's time of "5:45pm"
var d = new Date(1556214336316);
console.log('Date is: ' + d.toUTCString());
Assuming your value 1556214336.316 is a String coming back from a web API, you can remove the decimal and your conversion can be done like this (note you don't have to keep creating new Date objects):
convertDateToTimerFormat = (time) => {
const d = new Date( Number(time.replace(/\./g, '')) );
return `${d.getHours()}:${d.getMinutes()}:${d.getSeconds()}`;
};
console.log( 'time: ' + convertDateToTimerFormat('1556214336.316') );
Depending on your use, you may want to use getUTCHours() etc. instead.
I don't know about elegant, but this calculates and displays the expired time in h:mm:ss format:
console.log(convertDateToTimerFormat(1556215236.316));
function convertDateToTimerFormat(time){
// Converts `time` to milliseconds to make a JS Date object, then back to seconds
const expiredSeconds = Math.floor(new Date()/1000) - Math.floor(new Date(time * 1000)/1000);
// Calculates component values
const hours = Math.floor(expiredSeconds / 3600), //3600 seconds in an hour
minutes = Math.floor(expiredSeconds % 3600 / 60),
seconds = expiredSeconds % 3600 % 60;
// Adds initial zeroes if needed
if (minutes < 10) { minutes = "0" + minutes; }
if (seconds < 10) { seconds = "0" + seconds; }
// Returns a formatted string
return `${hours}:${minutes}:${seconds}`;
}

How to subtract a date with current date to get how long since it happened?

I get a date from a RSS FEED JSON file , the date is something like "2018-02-09 00:00:00" , It's a string but I know that I can turn it into integer using Number() or parseInt() and get the date with Date() , I want to get the time passed since it happened , Like 1 day ago , 2 hours ago .. etc , How to achieve that ?
Credit to Robert Gravelle at https://www.htmlgoodies.com/html5/javascript/calculating-the-difference-between-two-dates-in-javascript.html
Calculating the Difference between Two Known Dates
Unfortunately, calculating a date interval such as days, weeks, or months between two known dates is not as easy because you can't just add Date objects together. In order to use a Date object in any sort of calculation, we must first retrieve the Date's internal millisecond value, which is stored as a large integer. The function to do that is Date.getTime(). Once both Dates have been converted, subtracting the later one from the earlier one returns the difference in milliseconds. The desired interval can then be determined by dividing that number by the corresponding number of milliseconds. For instance, to obtain the number of days for a given number of milliseconds, we would divide by 86,400,000, the number of milliseconds in a day (1000 x 60 seconds x 60 minutes x 24 hours):
Date.daysBetween = function( date1, date2 )
{
//Get 1 day in milliseconds
var one_day=1000*60*60*24;
// Convert both dates to milliseconds
var date1_ms = date1.getTime();
var date2_ms = date2.getTime();
// Calculate the difference in milliseconds
var difference_ms = date2_ms - date1_ms;
// Convert back to days and return
return Math.round(difference_ms/one_day);
}
//Set the two dates
var y2k = new Date(2000, 0, 1);
var Jan1st2010 = new Date(y2k.getFullYear() + 10, y2k.getMonth(), y2k.getDate());
var today= new Date();
//displays 726
console.log( 'Days since '
+ Jan1st2010.toLocaleDateString() + ': '
+ Date.daysBetween(Jan1st2010, today));
The rounding is optional, depending on whether you want partial days or not.
First we define the desired units of time (conversions from milliseconds):
timeTypes={ year: 1000*60*60*24*365, month: 1000*60*60*24*30, day: 1000*60*60*24, hour: 1000*60*60, minute: 1000*60, second: 1000, millisecond: 1 };
Start with td being the time difference in milliseconds, the result of Date object .getTime() values:
td = d1.getTime() - d2.getTime();
And then we reduce it by the largest units and build a string as we go:
timeString='';
remaining=td;
for (i in timeTypes)
if (remaining > timeTypes[i]) {
count = parseInt(remaining/timeTypes[i]);
remaining -= timeTypes[i]*count;
timeString += count+' '+i+(count>1 ? 's' : '')+' ';
}
Now, timeString will contain something like:
1 month 9 days 42 seconds
This is treating every month as having 30 days, so that is a source of minor imprecision, but times less than a month are exact.

Categories