Convert milliseconds to more than 24 hours using Dayjs Library - javascript

How to convert milliseconds to more than 24 hours format? I am using Dayjs library but I could not figure out how to make the time format more than 24 hours.
In the code snippet below, the display should be 45:00:00.
For some reasons the output is not properly displaying on the code snippet so I also added it on jsfiddle.
dayjs.extend(dayjs_plugin_duration)
const dates = [
{
start: 1674748800000,
end: 1674831600000
},
{
start: 1674748800000,
end: 1674828000000
}
]
const totalEachDate = []
dates.filter( date => {
const dayjsStart = dayjs( date.start )
const dayjsEnd = dayjs( date.end )
const total = dayjs.duration( dayjsEnd.diff( dayjsStart ) ).$ms
totalEachDate.push( total ) // output: 23:00:00 and 22:00:00
} )
const addDates = totalEachDate.reduce( ( total, num ) => dayjs( total ) + dayjs( num ), 0 )
console.log( dayjs.duration( addDates ))
// this will display an object
<script src="https://cdnjs.cloudflare.com/ajax/libs/dayjs/1.11.7/plugin/duration.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dayjs#1/dayjs.min.js"></script>

To convert milliseconds to hours greater than 24 hours, you can use the Dayjs library and perform a simple calculation to convert the milliseconds to hours, minutes, and seconds.You can then display the results as a string using a template expression.
Here is the code that performs the conversion :
const totalMilliseconds = addDates
const totalSeconds = Math.floor(totalMilliseconds / 1000)
const totalMinutes = Math.floor(totalSeconds / 60)
const totalHours = Math.floor(totalMinutes / 60)
console.log(`${totalHours}:${totalMinutes % 60}:${totalSeconds % 60}`)
Adds zeros for the display of hours, minutes, and seconds.
console.log(`${("0" + totalHours).slice(-2)}:${("0" + (totalMinutes % 60)).slice(-2)}:${("0" + (totalSeconds % 60)).slice(-2)}`)

Related

React App - Why m count down is showing a dot whent the hours are equals to zero? And my minute is not 00 when pass of 59

The problem with the minutes is this.
And the problem with the hour dot is:
const [time, setTime] = useState(60 * 60)
const hour = time / 3600
let minutes = Math.floor(time / 60)
const seconds = time % 60;
const [hourLeft, hourRight] = String(hour).padStart(2, 0).split('')
const [minuteLeft, minuteRight] = String(minutes).padStart(2, 0).split('')
const [secondLeft, secondRight] = String(seconds).padStart(2, 0).split('')
useEffect(() => {
if(time > 0){
const timer = setTimeout(() => {
setTime(time - 1)
}, 1000)
}
}, [time])
Breaking the number up into left and right portions like that is really a strange way to go about it. Your code contains lots of errors.
First, you have
hour = time / 3600
You are not rounding, so therefore hour is going to always be a decimal between 0 and 1. So if you have 0.972222, you're then breaking up the digits of that number as if they were strings, so the first two will be 0 and . respectively.
What you need to be doing is getting the floor of this number. Then all of the other calculations after that are also incorrect. This is how you should be doing it:
const hour = Math.floor(time / 3600);
const minutes = Math.floor(time % 3600 / 60);
const seconds = Math.floor(time % 60);
Then forget about your crazy breaking numbers apart like strings and just pad them with zeroes. You can actually do it all in one step:
const hour = String(Math.floor(time / 3600)).padStart(2, 0);
const minutes = String(Math.floor(time % 3600 / 60)).padStart(2, 0);
const seconds = String(Math.floor(time % 60)).padStart(2, 0);
Then just display those values:
return (
<>
{hour}:{minutes}:{seconds}
</>
);
Or if you want to break them up into individual characters to display the background color like you have it, you could just do:
const timeStr = hour + ':' + minutes + ':' + seconds;
return (
<>
{timeStr.split('').map((char, index) => {
return <span key={index}>{char}</span>
})}
</>
);

Not counting down time correctly

I am creating a countdown website. I want it to count down from the current time the my celebration date 2019-11-29 00:00:00. I want the timezone to be in Australia Brisbane time zone. However, it seems to be that it keeps calculating the amount of time left till my celebration date wrong. Could someone tell me what I did wrong? And once the time hits 0, how can I get rid of the countdown and replace it with Its celebration time
function dateDiff(a, b) {
// Some utility functions:
const getSecs = dt => (dt.getHours() * 24 + dt.getMinutes()) * 60 + dt.getSeconds();
const getMonths = dt => dt.getFullYear() * 12 + dt.getMonth();
// 0. Convert to new date objects to avoid side effects
a = new Date(a);
b = new Date(b);
if (a > b) [a, b] = [b, a]; // Swap into order
// 1. Get difference in number of seconds during the day:
let diff = getSecs(b) - getSecs(a);
if (diff < 0) {
b.setDate(b.getDate()-1); // go back one day
diff += 24*60*60; // compensate with the equivalent of one day
}
// 2. Get difference in number of days of the month
let days = b.getDate() - a.getDate();
if (days < 0) {
b.setDate(0); // go back to (last day of) previous month
days += b.getDate(); // compensate with the equivalent of one month
}
// 3. Get difference in number of months
const months = getMonths(b) - getMonths(a);
return {
years: Math.floor(months/12),
months: months % 12,
days,
hours: Math.floor(diff/3600),
minutes: Math.floor(diff/60) % 24,
seconds: diff % 60
};
}
// Date to start on
var celebrationDate = new Date("2019-11-29 00:00:00").toLocaleString("en-US", {timeZone: "Australia/Brisbane"});
// Update the count every 1 second
!function refresh () {
const diff = dateDiff(new Date().toLocaleString("en-US", {timeZone: "Australia/Brisbane"}), celebrationDate);
document.getElementById("day-val").innerHTML = diff[Object.keys(diff)[2]];
document.getElementById("hour-val").innerHTML = diff[Object.keys(diff)[3]];
document.getElementById("min-val").innerHTML = diff[Object.keys(diff)[4]];
document.getElementById("sec-val").innerHTML = diff[Object.keys(diff)[5]];
setTimeout(refresh, 1000)
}()
<div id="day-val"></div><div>Days</div><br>
<div id="hour-val"></div><div>Hours</div><br>
<div id="min-val"></div><div>Minutes</div><br>
<div id="sec-val"></div><div>Seconds</div>
IF you are using moment.js
What you can do is use the diff and duration functions like so:
const now = moment();
const celebrationDate= moment("2019-11-30 00:00:00");
// this will get the difference between now and celebrationDate
const celebrationDateDiff = expiration.diff(now);
// convert it into duration
const duration = moment.duration(celebrationDateDiff);
You can then access the countdown like:
duration.days() // will return the number of days
duration.hours() // will return the number of remaining hours
duration.minutes() // will return the number of remaining minutes
Solution with plain javascript:
Get the clients time zone offset
Calculate the diff between client offset and "Australian/Brisbane" offset
Calculate time left by targetDate - currentDate - offsetDiff
Format the result to display it
Example:
const minToMS = min => min * 60 * 1000
const getCountDownFromMS = diff => {
const milliseconds = diff % 1000
diff = (diff - milliseconds) / 1000
const seconds = diff % 60
diff = (diff - seconds) / 60
const minutes = diff % 60
diff = (diff - minutes) / 60
const hours = diff % 24
diff = (diff - hours) / 24
const days = diff
return {
days,
hours,
minutes,
seconds,
milliseconds
}
}
const targetDate = new Date('2019-11-29 00:00:00')
// Getting offset with getTimezoneOffset is not reliable, using a database to get time zone offset is needed, like IANA Time Zone Database.
// moment.js internally uses IANA db
const tzOffset = targetDate.getTimezoneOffset() // Client browsers timezone offset in minutes
const target_tzOffset = -600 // Australia Brisbane timezone offset in minutes
const offset = minToMS(tzOffset - target_tzOffset)
const msLeft = targetDate - new Date() - offset
const result = getCountDownFromMS(msLeft)
You should also check moment.js as it has many useful features.
Example with moment.js:
const now = moment()
const target = moment.tz('2019-11-29 00:00:00', 'Australia/Brisbane')
const result = moment.duration(target.diff(now))

Calculate difference between 2 dates in ISO format in JavaScript/TS

I have 2 dates in ISO format like so:
startDate: "2018-09-14T00:20:12.200Z"
endDate: "2018-09-16T00:18:00.000Z"
What I'm trying to do is calculate the difference between those 2 days. So with the given dates it would be 1 Day, 21 Hours, 47 Minutes and 40 Seconds (pardon me if the subtraction is not correct).
Tried to do using the following:
const start = new Date(startDate).getTime();
const end = new Date(endDate).getTime();
return Math.abs(end - start).toString();
However this doesn't seem to work.
Any clues?
The following works. Things to note:
getTime() is not needed as the new Date() constructor returns the time in milliseconds.
The date should always be in RFC2822 or ISO formats, else it becomes useless across various browsers, even while using moment.js.
If you can use moment.js, Get time difference using moment.
Refer this to know why only the standardized formats need to be used.
var unitmapping = {"days":24*60*60*1000,
"hours":60*60*1000,
"minutes":60*1000,
"seconds":1000};
function floor(value)
{
return Math.floor(value)
}
function getHumanizedDiff(diff)
{
return floor(diff/unitmapping.days)+" days "+
floor((diff%unitmapping.days)/unitmapping.hours)+" hours "+
floor((diff%unitmapping.hours)/unitmapping.minutes)+" minutes "+
floor((diff%unitmapping.minutes)/unitmapping.seconds)+" seconds "+
floor((diff%unitmapping.seconds))+" milliseconds";
}
console.log(getHumanizedDiff(new Date("2018-09-16T00:18:00.000Z") - new Date("2018-09-14T00:20:12.200Z")));
console.log(getHumanizedDiff(new Date("2018-09-16T00:18:00.000Z") - new Date("2018-09-04T00:20:02.630Z")));
console.log(getHumanizedDiff(new Date("2018-09-17T00:16:04.000Z") - new Date("2018-09-14T00:20:12.240Z")));
var startDate = "2018-09-14T00:20:12.200Z"
var endDate = "2018-09-16T00:18:00.000Z"
const start = new Date(startDate).getTime();
const end = new Date(endDate).getTime();
const milliseconds = Math.abs(end - start).toString()
const seconds = parseInt(milliseconds / 1000);
const minutes = parseInt(seconds / 60);
const hours = parseInt(minutes / 60);
const days = parseInt(hours / 24);
const time = days + ":" + hours % 24 + ":" + minutes % 60 + ":" + seconds % 60;
console.log(time)
yBrodsky's suggestion to use moment.js is probably the best idea, but if you're curious how to do the math here, it would go something like this:
const start = new Date(startDate).getTime();
const end = new Date(endDate).getTime();
let seconds = Math.round(Math.abs(end - start) / 1000); // We'll round away millisecond differences.
const days = Math.floor(seconds / 86400);
seconds -= days * 86400;
const hours = Math.floor(seconds / 3600);
seconds -= hours * 3600;
minutes = Math.floor(seconds / 60);
seconds -= minutes * 60;
This leaves you with hours, minutes, and seconds as numbers that you can format into a string result however you like.

How to round time to the nearest quarter hour in JavaScript?

For example:
Given time: 08:22 => Rounded to: 08:15
Given time: 08:23 => Rounded to: 08:30
Should be pretty simple. But all I was able to produce is lengthy, not very good code to solve the issue. My mind's just gone blank.
Regards
Given that you have hours and minutes in variables (if you don't you can get them from the Date instance anyway by using Date instance functions):
var m = (parseInt((minutes + 7.5)/15) * 15) % 60;
var h = minutes > 52 ? (hours === 23 ? 0 : ++hours) : hours;
minutes can as well be calculated by using Math.round():
var m = (Math.round(minutes/15) * 15) % 60;
or doing it in a more javascript-sophisticated expression without any functions:
var m = (((minutes + 7.5)/15 | 0) * 15) % 60;
var h = ((((minutes/105) + .5) | 0) + hours) % 24;
You can check the jsPerf test that shows Math.round() is the slowest of the three while mainly the last one being the fastest as it's just an expression without any function calls (no function call overhead i.e. stack manipulation, although native functions may be treated differently in Javascript VM).
//----
This function round the time to the nearest quarter hour.
function roundTimeQuarterHour(time) {
var timeToReturn = new Date(time);
timeToReturn.setMilliseconds(Math.round(timeToReturn.getMilliseconds() / 1000) * 1000);
timeToReturn.setSeconds(Math.round(timeToReturn.getSeconds() / 60) * 60);
timeToReturn.setMinutes(Math.round(timeToReturn.getMinutes() / 15) * 15);
return timeToReturn;
}
With Time String
Here is a method that will round a time string like the one you presented. Eg "08:22"
let roundTime = (time, minutesToRound) => {
let [hours, minutes] = time.split(':');
hours = parseInt(hours);
minutes = parseInt(minutes);
// Convert hours and minutes to time in minutes
time = (hours * 60) + minutes;
let rounded = Math.round(time / minutesToRound) * minutesToRound;
let rHr = ''+Math.floor(rounded / 60)
let rMin = ''+ rounded % 60
return rHr.padStart(2, '0')+':'+rMin.padStart(2, '0')
}
// USAGE //
// Round time to 15 minutes
roundTime('8:07', 15); // "08:00"
roundTime('7:53', 15); // "08:00"
roundTime('7:52', 15); // "07:45"
With Hours and Minutes Already Split Up
You can use this method if you don't need to parse out the hour and minute strings like your example shows
let roundTime = (hours, minutes, minutesToRound) => {
// Convert hours and minutes to minutes
time = (hours * 60) + minutes;
let rounded = Math.round(time / minutesToRound) * minutesToRound;
let roundedHours = Math.floor(rounded / 60)
let roundedMinutes = rounded % 60
return { hours: roundedHours, minutes: roundedMinutes }
}
// USAGE //
// Round time to 15 minutes
roundTime(7, 52, 15); // {hours: 7, minutes: 45}
roundTime(7, 53, 15); // {hours: 8, minutes: 0}
roundTime(1, 10, 15); // {hours: 1, minutes: 15}
With Existing Date Object
Or, if you are looking to round an already existing date object to the nearest x minutes, you can use this method.
If you don't give it any date it will round the current time. In your case, you can round to the nearest 15 minutes.
let getRoundedDate = (minutes, d=new Date()) => {
let ms = 1000 * 60 * minutes; // convert minutes to ms
let roundedDate = new Date(Math.round(d.getTime() / ms) * ms);
return roundedDate
}
// USAGE //
// Round existing date to 5 minutes
getRoundedDate(15, new Date()); // 2018-01-26T00:45:00.000Z
// Get current time rounded to 30 minutes
getRoundedDate(30); // 2018-01-26T00:30:00.000Z
The code here is a little verbose but I'm sure you'll see how you could combine the lines to make this shorter. I've left it this way to clearly show the steps:
var now = new Date();
var mins = now.getMinutes();
var quarterHours = Math.round(mins/15);
if (quarterHours == 4)
{
now.setHours(now.getHours()+1);
}
var rounded = (quarterHours*15)%60;
now.setMinutes(rounded);
document.write(now);
Divide by 9e5 milliseconds (15 * 60 * 1000), round, and multiply back by 9e5 :
const roundToQuarter = date => new Date(Math.round(date / 9e5) * 9e5)
console.log( roundToQuarter(new Date("1999-12-31T23:52:29.999Z")) ) // 1999-12-31T23:45:00
console.log( roundToQuarter(new Date("1999-12-31T23:52:30.000Z")) ) // 2000-01-01T00:00:00
console.log( roundToQuarter(new Date) )
I use these code:
function RoundUp(intervalMilliseconds, datetime){
datetime = datetime || new Date();
var modTicks = datetime.getTime() % intervalMilliseconds;
var delta = modTicks === 0 ? 0 : datetime.getTime() - modTicks;
delta += intervalMilliseconds;
return new Date(delta);
}
function RoundDown(intervalMilliseconds, datetime){
datetime = datetime || new Date();
var modTicks = datetime.getTime() % intervalMilliseconds;
var delta = modTicks === 0 ? 0 : datetime.getTime() - modTicks;
return new Date(delta);
}
function Round(intervalMilliseconds, datetime){
datetime = datetime || new Date();
var modTicks = datetime.getTime() % intervalMilliseconds;
var delta = modTicks === 0 ? 0 : datetime.getTime() - modTicks;
var shouldRoundUp = modTicks > intervalMilliseconds/2;
delta += shouldRoundUp ? intervalMilliseconds : 0;
return new Date(delta);
}
Round to the nearest 5 minutes:
//with current datetime
var result = Round(5 * 60 * 1000);
//with a given datetime
var dt = new Date();
var result = Round(5 * 60 * 1000, dt);
There is an NPM package #qc/date-round that can be used. Given that you have a Date instance to be rounded
import { round } from '#qc/date-round'
const dateIn = ...; // The date to be rounded
const interval = 15 * 60 * 1000; // 15 minutes (aka quarter hour)
const dateOut = round(dateIn, interval)
Then you can use date-fns to format the date
import format from 'date-fns/format';
console.log(format(dateOut, 'HH:mm')) // 24-hr
console.log(format(dateOut, 'hh:mm a')) // 12-hr
Another one with date-fns (not mandatory)
import {getMinutes, setMinutes, setSeconds, setMilliseconds} from 'date-fns'
let date = new Date();
let min = getMinutes(date);
let interval = 3 // in minutes
let new_min = min - min%interval + interval;
let new_date = setMilliseconds(setSeconds(setMinutes(date,new_min),0),0)
console.log('Orignal Date : ' + date);
console.log('Original Minute : ' + min);
console.log('New Minute : ' + new_min);
console.log('New Date : ' + new_date);
Pass the interval in milliseconds get the next cycle in roundUp order
Example if I want next 15 minute cycle from current time then call this method like *calculateNextCycle(15 * 60 * 1000);*
Samething for quarter hour pass the interval
function calculateNextCycle(interval) {
const timeStampCurrentOrOldDate = Date.now();
const timeStampStartOfDay = new Date().setHours(0, 0, 0, 0);
const timeDiff = timeStampCurrentOrOldDate - timeStampStartOfDay;
const mod = Math.ceil(timeDiff / interval);
return new Date(timeStampStartOfDay + (mod * interval));
}
console.log(calculateNextCycle(15 * 60 * 1000));
This method is specifically for Vue.js, it takes a time, and returns to the nearest entered increment, I based this on an above answer, but this is for Vue specifically using echma-6 standards. It will return T:06:00:00, if you fed 06:05 into it. This is used specifically with vuetify's v-calendar to choose a time in weeklyor daily format.
This answer also adds the 0 for like 06 hrs. Which is where this differs from the above answers. If you change the 30 to 15
methods: {
roundTimeAndFormat(datetime, roundTo) {
const hrsMins = datetime.split(':')
let min = ((((hrsMins[1] + 7.5) / roundTo) | 0) * roundTo) % 60
let hr = (((hrsMins[1] / 105 + 0.5) | 0) + hrsMins[0]) % 24
if (Number(hr) < 10) {
hr = ('0' + hr).slice(-2)
}
if (min === 0) {
min = ('0' + min).slice(-2)
}
return 'T' + hr + ':' + min + ':00'
}
}
You would just call:
this.roundTimeAndFormat(dateTime, 15)
And you would get the time to the nearest 15min interval.
If you enter, 11:01, you'd get T11:00:00
Might help others. For any language. Mainly trick with round function.
roundedMinutes = yourRoundFun(Minutes / interval) * interval
E.g. The interval could be 5 minutes, 10 minutes, 15 minutes, 30 minutes.
Then rounded minutes can be reset to the respective date.
yourDateObj.setMinutes(0)
yourDateObj.setMinutes(roundedMinutes)
also if required then
yourDateObj.setSeconds(0)
yourDateObj.setMilliSeconds(0)
Simple?

Javascript, Hour comparisson

Having two strings (start and end time) in such form "16:30", "02:13" I want to compare them and check if the gap is greater than 5 mins.
How can this be achieved in Javascript in an easy way?
function parseTime(time) {
var timeArray = time.split(/:/);
// Using Jan 1st, 2010 as a "base date". Any other date should work.
return new Date(2010, 0, 1, +timeArray[0], +timeArray[1], 0);
}
var diff = Math.abs(parseTime("16:30").getTime() - parseTime("02:13").getTime());
if (diff > 5 * 60 * 1000) { // Difference is in milliseconds
alert("More that 5 mins.");
}
Do you need to wrap over midnight? Then this is more difficult. For example, 23:59 and 00:01 will produce a difference of 23 hours 58 minutes and not 2 minutes.
If that's the case you need to define your case more closely.
You can do as following:
if (((Date.parse("16:30") - Date.parse("02:13")) / 1000 / 60) > 5)
{
}
// time is a string having format "hh:mm"
function Time(time) {
var args = time.split(":");
var hours = args[0], minutes = args[1];
this.milliseconds = ((hours * 3600) + (minutes * 60)) * 1000;
}
Time.prototype.valueOf = function() {
return this.milliseconds;
}
// converts the given minutes to milliseconds
Number.prototype.minutes = function() {
return this * (1000 * 60);
}
Subtracting the times forces the object to evaluate it's value by calling the valueOf method that returns the given time in milliseconds. The minutes method is another convenience method to convert the given number of minutes to milliseconds, so we can use that as a base for comparison throughout.
new Time('16:30') - new Time('16:24') > (5).minutes() // true
This includes checking whether midnight is between the two times (as per your example).
var startTime = "16:30", endTime = "02:13";
var parsedStartTime = Date.parse("2010/1/1 " + startTime),
parsedEndTime = Date.parse("2010/1/1 " + endTime);
// if end date is parsed as smaller than start date, parse as the next day,
// to pick up on running over midnight
if ( parsedEndTime < parsedStartTime ) ed = Date.parse("2010/1/2 " + endTime);
var differenceInMinutes = ((parsedEndTime - parsedStartTime) / 60 / 1000);
if ( differenceInMinutes > 5 ) {
alert("More than 5 mins.");
}

Categories

Resources