Timestamp: Calculate full date and minutes difference in moment.js - javascript

I'm calculating the time in minutes using timestamp and moment.
So far I can format timestamp with moment but the calculation is a NaN.
This is my code:
function (val) {
var a = moment.unix(val[0]).format("YYYY-MM-DD hh:mm:ss") // timestamp: 1672531200
var b = moment.unix(val[1]).format("YYYY-MM-DD hh:mm:ss") // timestamp: 1672551000
var diff = Math.round((b - a) / 60000)
console.log('A', a) // res: 2023-01-01 12:00:00
console.log('B', b) // res: 2023-01-01 05:30:00
console.log('difference', diff) // res: NaN
return diff + (diff > 1 ? ' minutes' : ' minute')
}
Could you please explain me what I'm doing wrong here?

With the .format("YYYY-MM-DD hh:mm:ss") at the end of the first two lines, you are trying to substract two strings.
Just remove the format() calls and it should work :
function calcul(val) {
var a = moment.unix(val[0]) // timestamp: 1672531200
var b = moment.unix(val[1]) // timestamp: 1672551000
var diff = Math.round((b - a) / 60000)
return diff + (diff > 1 ? ' minutes' : ' minute')
}
Regards

Related

How to convert current time to EST to ISO 8601 string format? [duplicate]

how do I format a javascript date like ISO format, but in local time?
with myDate.toISOString() I am getting the time as: "2012-09-13T19:12:23.826Z"
but here, it is 22:13, so how do I include the timezone in above format?
I ended up doing...
pad=function(e,t,n){n=n||"0",t=t||2;while((""+e).length<t)e=n+e;return e}
c = new Date()
c.getFullYear()+"-"+pad(c.getMonth()+1)+"-"+pad(c.getDate()-5)+"T"+c.toLocaleTimeString().replace(/\D/g,':')+"."+pad(c.getMilliseconds(),3)
No library required! For some Date object, e.g. t = new Date()
convert the local time zone offset from minutes to milliseconds
z = t.getTimezoneOffset() * 60 * 1000
subtract the offset from t
tLocal = t-z
create shifted Date object
tLocal = new Date(tLocal)
convert to ISO format string
iso = tLocal.toISOString()
drop the milliseconds and zone
iso = iso.split(".")[0]
replace the ugly 'T' with a space
iso = iso.replace('T', ' ')
Result is a nice ISO-ish format date-time string like "2018-08-01 22:45:50" in the local time zone.
A bit of a hack but can be done in one line by taking advantage of the fact that Sweden uses a format very close to ISO:
// Returns a string like 2021-01-17T01:59:57
function dateToISOButLocal(date) {
return date.toLocaleString('sv').replace(' ', 'T');
}
To support milliseconds:
return date.toLocaleString('sv', {year:'numeric', month:'numeric', day:'numeric', hour:'numeric', minute:'numeric', second:'numeric', fractionalSecondDigits: 3}).replace(',', '.').replace(' ', 'T');
I went with what Denis Howe said, below as a ready made function for convenience.
Also one fix: in the original answer t-z does not work because t is a Date, not milliseconds.
function dateToISOLikeButLocal(date) {
const offsetMs = date.getTimezoneOffset() * 60 * 1000;
const msLocal = date.getTime() - offsetMs;
const dateLocal = new Date(msLocal);
const iso = dateLocal.toISOString();
const isoLocal = iso.slice(0, 19);
return isoLocal;
}
With this I get the kind of string that needed as a URL parameter:
"2018-11-16T12:23:50"
AFAIK you can't format dates in javascript (without using external libraries). The best you could do is "format it yourself". I mean:
var date = new Date();
var year = date.getFullYear();
var month = date......
var ISOdate = year + "-" + month + "-" + .... ;
But there are some good libraries that will let you format dates! (read "format" as in library.getDate("YYYY-MM-DD.........");)
EDIT:
Moment.js seems the thing you're looking for: http://momentjs.com/
Although answers here might work, there's nothing like a simple one-liner:
new Date(new Date().getTime() - new Date().getTimezoneOffset() * 60 * 1000).toISOString()
Explanation for those who are interested:
We create a new instance of Date (the outer one).
We give it another instance of Date (in milliseconds) from which we subtract the timezone offset (in milliseconds too, either positive or negative). All of this we format into ISO
I don't quite understand which date did you need
but I think you need
const ISOLocaleString = d => {
const pad = n => n < 10 ? '0'+n : n;
return d.getFullYear()+'-'
+ pad(d.getMonth()+1)+'-'
+ pad(d.getDate())+'T'
+ pad(d.getHours())+':'
+ pad(d.getMinutes())+':'
+ pad(d.getSeconds())+'Z'
}
or
const ISOUTCLocaleString = d => {
const pad = n => n<10 ? '0'+n : n;
return d.getUTCFullYear()+'-'
+ pad(d.getUTCMonth()+1)+'-'
+ pad(d.getUTCDate())+'T'
+ pad(d.getUTCHours())+':'
+ pad(d.getUTCMinutes())+':'
+ pad(d.getUTCSeconds())+'Z'
}
In the original post, the current ISO date is "2012-09-13T19:12:23.826Z"
If what is wanted is a date that respects ISO norm but reflects the local offset from UTC time, the target answer should be "2012-09-13T22:12:23.826+03:00".
Best answer in the post bellow, with code snippet that respects the ISO 8601 format / RFC 3339
https://stackoverflow.com/a/17415677/1563072
Another method is to define a prototype on the Date object that leverages the built-in toISOString method (a separate function is also provided):
// Extend Date.prototype
Date.prototype.toLocalISOString = function() {
// Get the local offset for the date in minutes
let offsetMins = this.getTimezoneOffset();
// Get a time value adjusted for the offset
let localTimeMs = this - offsetMins * 6e4;
// Make a new Date so don't affect this
let date = new Date(localTimeMs);
// Get the local offset sign (ECMAScript sign is opposite to usual)
let utcOffsetSign = offsetMins > 0? '-' : '+';
// Remove sign from offsetMins
offsetMins = Math.abs(offsetMins);
// Get offset hours and minutes, padd to 2 digits
let utcOffsetHr = String(offsetMins / 60 | 0).padStart(2,'0');
let utcOffsetMin = String(offsetMins % 60).padStart(2,'0');
// Build offset string
let utcOffsetString = `${utcOffsetSign}${utcOffsetHr}:${utcOffsetMin}`;
// Return as adjusted ISO 8601 format string with adjusted offset
return date.toISOString().replace('Z', utcOffsetString);
};
// E.g.
let date = new Date();
// Like 2020-08-04T14:52:38.613-07:00
console.log(`UTC : ${date.toISOString()}\n` +
`Local: ${date.toLocalISOString()}`);
// Stand alone function
function toISOLocal(date) {
let offsetMins = date.getTimezoneOffset();
let d = new Date(date - offsetMins*6e4);
let offsetSign = offsetMins > 0? '-' : '+';
offsetMins = Math.abs(offsetMins);
let offsetHr = String(offsetMins / 60 | 0).padStart(2,'0');
let offsetMin = String(offsetMins % 60).padStart(2,'0');
return d.toISOString().replace('Z', `${offsetSign}${offsetHr}:${offsetMin}`);
}
// Like 2020-08-04T14:52:38.613-07:00
console.log(`fn : ${toISOLocal(date)}`);
ISO 8601 is simply a way of formatting dates and can as such can be applied to any time zone.
Have you tried the timeZone option to the Date object's toLocaleString method?
This question has answers with examples.
This is the method I use. It takes care to add zeros if date/month/hour etc is single digit number (for example turns '6' to '06')
function formatLikeISO (d: Date): string {
let lengthChecker = (str) => {
if (str.length == 1) { return '0' + str; }
return str;
}
let theDate = lengthChecker(String(d.getDate()));
let month = lengthChecker(String(d.getMonth() + 1));
let mins = lengthChecker(String(d.getMinutes()));
let hours = lengthChecker(String(d.getHours()));
let secs = lengthChecker(String(d.getSeconds()));
let formatted =
d.getFullYear() + '-' +
month + '-' +
theDate + ' ' +
hours + ':' +
mins + ':' +
secs;
return formatted;
}
This will output this kind of format:
"2021-06-30 11:31:34"
There's no direct way to do this. However, you can use toLocaleString to create a string that you can easily parse to make it an ISO string.
This works on node:
function getLocalIsoTime(time, timezone) {
const local = time.toLocaleString("en-US", {timeZone: timezone, hour12: false, year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
return `${local.substr(6, 4)}-${local.substr(0, 2)}-${local.substr(3, 2)}T${local.substr(12, 8)}`;
}
console.log(getLocalIsoTime(new Date(), 'Asia/Kolkata'));
A simpler version works on node 15+ and on most modern browsers:
function getLocalIsoTime(time, timezone) {
return time.toLocaleString("en-CA", {timeZone: timezone, hour12: false}).replace(/, /, "T");
}
console.log(getLocalIsoTime(new Date(), 'Asia/Kolkata'));
Based on https://stackoverflow.com/a/68191554/833960, but I wanted the ms to be present and consistent width output of 3 digits for ms.
function formatLikeISO(d: Date): string {
let lengthChecker = (str: string, targetLen = 2) => {
if (str.length < targetLen) {
return str.padStart(targetLen, '0')
}
return str
}
let day = lengthChecker(String(d.getDate()))
let month = lengthChecker(String(d.getMonth() + 1))
let mins = lengthChecker(String(d.getMinutes()))
let hours = lengthChecker(String(d.getHours()))
let secs = lengthChecker(String(d.getSeconds()))
let ms = lengthChecker(String(d.getMilliseconds()), 3)
let formatted =
d.getFullYear() +
'-' +
month +
'-' +
day +
' ' +
hours +
':' +
mins +
':' +
secs +
'.' +
ms
return formatted
}
Output:
2023-02-13 10:23:59.025
2023-02-13 10:23:59.026
2023-02-13 10:23:59.026
2023-02-13 10:23:59.030
2023-02-13 10:23:59.438
2023-02-13 10:23:59.438

Time difference between an ISO 8601 date and now

I have a comment section on my website and each message have its created_at date time. After fetching it from the MariaDB database, I get a string like "2021-06-15T12:45:28.000Z" (ISO 8601). Then, I convert it to a "x minutes ago" text instead of the full date.
But then, I'm having some trouble when the date is parsed.
const epochs = [
["année", 31536000],
["mois", 2592000],
["jour", 86400],
["heure", 3600],
["minute", 60],
["seconde", 1]
];
function getInterval(timeAgo) {
for (let [ name, seconds ] of epochs) {
const interval = Math.floor(timeAgo / seconds);
if (interval >= 1) {
return { interval: interval, epoch: name };
}
}
}
function dateToString(d) {
const date = new Date(d);
console.log("Created at:", date);
console.log("Now:", new Date());
const timeAgo = Math.floor((new Date() - date) / 1000);
console.log("Time ago:", timeAgo);
const { interval, epoch } = getInterval(timeAgo);
const plural = (interval === 1 || epoch.slice(-1) === "s") ? "" : "s";
console.log("----------------------------");
return `Il y a ${interval} ${epoch}${plural}`;
}
dateToString("2021-06-15 12:45:28"); // Works fine
dateToString("2021-06-15T12:45:28.000Z"); // The "timeAgo" is negative
Subtracting the ISO date gives a negative number. I'm pretty sure this is a timezone problem because the
minimal value of the substraction is almost -7200 which is two hour and I'm in a UTC+2 timezone.
Have you any idea how can I fix this?
Thanks
Try adding or subtracting the timezoneOffset of the local computer from the UTC you get when you pass Z
I fixed your plural too
const epochs = {
"années": 31536000,
"mois": 2592000,
"jours": 86400,
"heures": 3600,
"minutes": 60,
"secondes": 1
};
const singular = {
"années": "ans",
"mois": "mois",
"jours": "jour",
"heures": "heure",
"minutes": "minute",
"secondes": "seconde"
};
const getInterval = timeAgo => {
const epoch = Object.entries(epochs).filter(([key, val]) => timeAgo >= val).shift();
const obj = {
epoch: epoch[0],
interval: parseInt(timeAgo / epoch[1])
}
if (obj.interval === 1) obj.epoch = singular[obj.epoch]
return obj
};
const aMinute = 60 * 1000
function dateToString(d) {
const date = new Date(d);
if (d.includes("Z")) {
let tzo = date.getTimezoneOffset();
tzo = (tzo > 0 ? tzo * -1 : tzo);
tzo *= aMinute
date.setTime(date.getTime() + tzo)
}
console.log("Created at:", date.toLocaleString());
console.log("Now:", new Date());
const timeAgo = Math.floor((new Date() - date) / 1000);
console.log("Time ago:", timeAgo);
console.log(getInterval(timeAgo))
const { epoch, interval } = getInterval(timeAgo);
console.log(epoch)
console.log("----------------------------");
return `Il y a ${interval} ${epoch}`;
}
console.log(
dateToString("2021-06-15 12:45:28"), "\n",
dateToString("2021-06-15T12:45:28.000Z"), "\n",
dateToString("2019-06-15T12:45:28.000Z"), "\n"
)

Convert seconds to HH-MM with JavaScript?

I have been using this excellent function for HH:MM:SS, but how could I modify it to return only HH:MM with either the seconds truncated or rounded.
function formatSeconds(seconds)
{
var date = new Date(1970,0,1);
date.setSeconds(seconds);
return date.toTimeString().replace(/.*(\d{2}:\d{2}:\d{2}).*/, "$1");
}
function formatSeconds(seconds)
{
var date = new Date(1970,0,1);
date.setSeconds(seconds);
return date.toTimeString().replace(/.*?(\d{2}:\d{2}).*/, "$1");
}
remove the last \d{2} and add ? after the first *
The problem with using a Date to format seconds is that it can't handle times longer than 24 hours and the vagaries of Dates. Simply reformat the value as required:
function formatSeconds(seconds) {
function z(n) {return (n < 10 ? '0' : '') + n;}
return z(seconds / 3600 | 0) + ':' + z((seconds % 3600) / 60 | 0)
}
// Some examples
[0,1,61,3600,3660,765467].forEach(function (seconds) {
console.log(seconds + ' -> ' + formatSeconds(seconds))
});
No Date, no regular expression, no library, no dependencies and works in every host that ever supported ECMAScript.
Though ideal way would be to use moment.js but if you wish to use custom function, you can try something like this:
function formatSeconds(milliseconds, format) {
var dateObj = new Date(milliseconds);
function getDoubleDigits(value){
return ("0" + value).slice(-2)
}
var o = {
DD: getDoubleDigits(dateObj.getDate()),
MM: getDoubleDigits(dateObj.getMonth() + 1),
YY: dateObj.getYear(),
YYYY: dateObj.getFullYear(),
hh: getDoubleDigits(dateObj.getHours()),
mm: getDoubleDigits(dateObj.getMinutes()),
ss: getDoubleDigits(dateObj.getSeconds())
}
var dilimeter = format.match(/[^\w]/)[0];
return format.split(dilimeter).map(function(f){
return o[f];
}).join(dilimeter);
}
var today = new Date();
console.log(formatSeconds(+today, "DD-MM-YYYY"))
console.log(formatSeconds(+today, "hh:mm"))

jqm-calendar time format (24 hour default...would prefer 12 hour)

I am using jqm-calendar for my jquery mobile app. Right now the default time format is 24 hours. I would like to change it to 12 hours.
Thank you.
https://github.com/JWGmeligMeyling/jqm-calendar
In file jw-jqm-cal.js
add this function:
function tConvert (time) {
// Check correct time format and split into components
time = time.toString ().match (/^([01]\d|2[0-3])(:)([0-5]\d)(:[0-5]\d)?$/) || [time];
if (time.length > 1) { // If time format correct
time = time.slice (1); // Remove full string match value
time[5] = +time[0] < 12 ? ' AM' : ' PM'; // Set AM/PM
time[0] = +time[0] % 12 || 12; // Adjust hours
}
return time.join (''); // return adjusted time or original string
}
and insert this 2 lines in function plugin.settings.eventHandler.getEventsOnDay(begin, end, function(list_of_events):
beginTime =tConvert(beginTime );
endTime=tConvert(endTime);
EDIT
insert before: timeString = beginTime + "-" + endTime :**
...
beginTime =tConvert(beginTime );
endTime=tConvert(endTime);
timeString = beginTime + "-" + endTime,
...

How to use format() on a moment.js duration?

Is there any way I can use the moment.js format method on duration objects? I can't find it anywhere in the docs and it doesn't seen to be an attribute on duration objects.
I'd like to be able to do something like:
var diff = moment(end).unix() - moment(start).unix();
moment.duration(diff).format('hh:mm:ss')
Also, if there are any other libraries which can easily accommodate this sort of functionality, I'd be interested in recommendations.
Thanks!
// set up
let start = moment("2018-05-16 12:00:00"); // some random moment in time (in ms)
let end = moment("2018-05-16 12:22:00"); // some random moment after start (in ms)
let diff = end.diff(start);
// execution
let f = moment.utc(diff.asMilliseconds()).format("HH:mm:ss.SSS");
alert(f);
Have a look at the JSFiddle
convert duration to ms and then to moment:
moment.utc(duration.as('milliseconds')).format('HH:mm:ss')
We are looking into adding some kind of formatting to durations in moment.js. See https://github.com/timrwood/moment/issues/463
A couple other libraries that might help out are http://countdownjs.org/ and https://github.com/icambron/twix.js
Use this plugin Moment Duration Format.
Example:
moment.duration(123, "minutes").format("h:mm");
Use this line of code:
moment.utc(moment.duration(4500, "seconds").asMilliseconds()).format("HH:mm:ss")
var diff = moment(end).unix() - moment(start).unix();
moment.utc(moment.duration(diff).asMilliseconds()).format("HH:mm:ss.SSS");
The best scenario for my particular use case was:
var duration = moment.duration("09:30"),
formatted = moment.utc(duration.asMilliseconds()).format("HH:mm");
This improves upon #Wilson's answer since it does not access private internal property _data.
You don't need .format. Use durations like this:
const duration = moment.duration(83, 'seconds');
console.log(duration.minutes() + ':' +duration.seconds());
// output: 1:23
I found this solution here: https://github.com/moment/moment/issues/463
EDIT:
And with padding for seconds, minutes and hours:
const withPadding = (duration) => {
if (duration.asDays() > 0) {
return 'at least one day';
} else {
return [
('0' + duration.hours()).slice(-2),
('0' + duration.minutes()).slice(-2),
('0' + duration.seconds()).slice(-2),
].join(':')
}
}
withPadding(moment.duration(83, 'seconds'))
// 00:01:23
withPadding(moment.duration(6048000, 'seconds'))
// at least one day
I needed to do this for work as a requirement to display the hours in this format.
At first I tried this.
moment.utc(totalMilliseconds).format("HH:mm:ss")
However anything over 24 hours and the hours reset to 0.
But the minutes and seconds were accurate.
So I used only that part for the minutes and seconds.
var minutesSeconds = moment.utc(totalMilliseconds).format("mm:ss")
Now all I need is the total hours.
var hours = moment.duration(totalMilliseconds).asHours().toFixed()
And to get that format that we all want we just glue it together.
var formatted = hours + ":" + minutesSeconds
if totalMilliseconds is 894600000 this will return 249:30:00.
Hope that helped. Leave any questions in the comments. ;)
I use:
var duration = moment.duration("09:30");
var str = moment(duration._data).format("HH:mm");
And I get "09:30" in var str.
if diff is a moment
var diff = moment(20111031) - moment(20111010);
var formated1 = moment(diff).format("hh:mm:ss");
console.log("format 1: "+formated1);
If you're willing to use a different javascript library, numeral.js can format seconds as follows (example is for 1000 seconds):
var string = numeral(1000).format('00:00');
// '00:16:40'
If all hours must be displayed (more than 24) and if '0' before hours is not necessary, then formatting can be done with a short line of code:
Math.floor(duration.as('h')) + moment.utc(duration.as('ms')).format(':mm:ss')
Based on ni-ko-o-kin's answer:
meassurements = ["years", "months", "weeks", "days", "hours", "minutes", "seconds"];
withPadding = (duration) => {
var step = null;
return meassurements.map((m) => duration[m]()).filter((n,i,a) => {
var nonEmpty = Boolean(n);
if (nonEmpty || step || i >= a.length - 2) {
step = true;
}
return step;
}).map((n) => ('0' + n).slice(-2)).join(':')
}
duration1 = moment.duration(1, 'seconds');
duration2 = moment.duration(7200, 'seconds');
duration3 = moment.duration(604800, 'seconds');
withPadding(duration1); // 00:01
withPadding(duration2); // 02:00:00
withPadding(duration3); // 01:07:00:00:00
I use the classic format function in these cases:
var diff = moment(end).unix() - moment(start).unix();
//use unix function instead of difference
moment.unix(diff).format('hh:mm:ss')
This is a hack because the time diff is treated as a standard moment date, an early epoch date time, but it doesn't matter to our goal and you don't need any plugin
Short version (one-liner):
moment.duration(durationInMs).asHours()|0||"00" + ":" + moment.utc(durationInMs).format("mm:ss")
Extended version:
export const formatDuration = (durationInMs) => {
const hours = Math.floor(moment.duration(durationInMs).asHours()) || "00"
return hours + ":" + moment.utc(durationInMs).format("mm:ss")
}
Example cases:
To format moment duration to string
var duration = moment.duration(86400000); //value in milliseconds
var hours = duration.hours();
var minutes = duration.minutes();
var seconds = duration.seconds();
var milliseconds = duration.milliseconds();
var date = moment().hours(hours).minutes(minutes).seconds(seconds).millisecond(milliseconds);
if (is12hr){
return date.format("hh:mm:ss a");
}else{
return date.format("HH:mm:ss");
}
if you use angular add this to your filters:
.filter('durationFormat', function () {
return function (value) {
var days = Math.floor(value/86400000);
value = value%86400000;
var hours = Math.floor(value/3600000);
value = value%3600000;
var minutes = Math.floor(value/60000);
value = value%60000;
var seconds = Math.floor(value/1000);
return (days? days + ' days ': '') + (hours? hours + ' hours ': '') + (minutes? minutes + ' minutes ': '') + (seconds? seconds + ' seconds ': '')
}
})
usage example
<div> {{diff | durationFormat}} </div>
My solution that does not involve any other library and it works with diff > 24h
var momentInSeconds = moment.duration(n,'seconds')
console.log(("0" + Math.floor(momentInSeconds.asHours())).slice(-2) + ':' + ("0" + momentInSeconds.minutes()).slice(-2) + ':' + ("0" + momentInSeconds.seconds()).slice(-2))
How to correctly use moment.js durations?
|
Use moment.duration() in code
First you need to import moment and moment-duration-format.
import moment from 'moment';
import 'moment-duration-format';
Then, use duration function. Let us apply the above example: 28800 = 8 am.
moment.duration(28800, "seconds").format("h:mm a");
🎉Well, you do not have above type error. 🤔Do you get a right value 8:00 am ? No…, the value you get is 8:00 a. Moment.js format is not working as it is supposed to.
💡The solution is to transform seconds to milliseconds and use UTC time.
moment.utc(moment.duration(value, 'seconds').asMilliseconds()).format('h:mm a')
All right we get 8:00 am now. If you want 8 am instead of 8:00 am for integral time, we need to do RegExp
const time = moment.utc(moment.duration(value, 'seconds').asMilliseconds()).format('h:mm a');
time.replace(/:00/g, '')
How about native javascript?
var formatTime = function(integer) {
if(integer < 10) {
return "0" + integer;
} else {
return integer;
}
}
function getDuration(ms) {
var s1 = Math.floor(ms/1000);
var s2 = s1%60;
var m1 = Math.floor(s1/60);
var m2 = m1%60;
var h1 = Math.floor(m1/60);
var string = formatTime(h1) +":" + formatTime(m2) + ":" + formatTime(s2);
return string;
}
Use moment-duration-format.
Client Framework (ex: React)
import moment from 'moment';
import momentDurationFormatSetup from 'moment-duration-format';
momentDurationFormatSetup(moment);
const breakLengthInMinutes = moment.duration(breakLengthInSeconds, 's').format('m');
Server (node.js)
const moment = require("moment-timezone");
const momentDurationFormatSetup = require("moment-duration-format");
momentDurationFormatSetup(moment);
const breakLengthInMinutes = moment.duration(breakLengthInSeconds, 's').format('m');
moment.duration(x).format() has been deprecated.
You can usemoment.utc(4366589).format("HH:mm:ss") to get the desired response.
console.log(moment.utc(4366589).format("HH:mm:ss"))
<script src="https://momentjs.com/downloads/moment.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
const duration = moment.duration(62, 'hours');
const n = 24 * 60 * 60 * 1000;
const days = Math.floor(duration / n);
const str = moment.utc(duration % n).format('H [h] mm [min] ss [s]');
console.log(`${days > 0 ? `${days} ${days == 1 ? 'day' : 'days'} ` : ''}${str}`);
Prints:
2 days 14 h 00 min 00 s
There is no longer (if there ever was) any need to convert duration to utc to solve this issue. This is like converting a base10 "1" to binary and then saying that since output "1" looks like base10 we'll have no issues assuming this is a base10 value for any further operations.
Use moment-duration-format and note that with { trim: false } you can prevent trimming:
moment.duration(1000000, "seconds").format("hh:mm:ss", { trim: false })
> "277:46:40"
moment.duration(0, "seconds").format("hh:mm:ss", { trim: false })
> "00:00:00"
Let's compare this with the not recommended method of using abusing utc:
moment.utc(moment.duration(1000000, "seconds").asMilliseconds()).format('HH:mm:ss')
> "13:46:40"
Just moment.js without any other plugins
moment().startOf('day').seconds(duration).format('HH:mm:ss')
import * as moment from 'moment'
var sleep = require('sleep-promise');
(async function () {
var t1 = new Date().getTime();
await sleep(1000);
var t2 = new Date().getTime();
var dur = moment.duration(t2-t1);
console.log(`${dur.hours()}h:${dur.minutes()}m:${dur.seconds()}s`);
})();
0h:0m:1s
You can use numeral.js to format your duration:
numeral(your_duration.asSeconds()).format('00:00:00') // result: hh:mm:ss
This can be used to get the first two characters as hours and last two as minutes. Same logic may be applied to seconds.
/**
* PT1H30M -> 0130
* #param {ISO String} isoString
* #return {string} absolute 4 digit number HH:mm
*/
const parseIsoToAbsolute = (isoString) => {
const durations = moment.duration(isoString).as('seconds');
const momentInSeconds = moment.duration(durations, 'seconds');
let hours = momentInSeconds.asHours().toString().length < 2
? momentInSeconds.asHours().toString().padStart(2, '0') : momentInSeconds.asHours().toString();
if (!Number.isInteger(Number(hours))) hours = '0'+ Math.floor(hours);
const minutes = momentInSeconds.minutes().toString().length < 2
? momentInSeconds.minutes().toString().padEnd(2, '0') : momentInSeconds.minutes().toString();
const absolute = hours + minutes;
return absolute;
};
console.log(parseIsoToAbsolute('PT1H30M'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment-with-locales.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
If you use Angular >2, I made a Pipe inspired by #hai-alaluf answer.
import {Pipe, PipeTransform} from "#angular/core";
#Pipe({
name: "duration",
})
export class DurationPipe implements PipeTransform {
public transform(value: any, args?: any): any {
// secs to ms
value = value * 1000;
const days = Math.floor(value / 86400000);
value = value % 86400000;
const hours = Math.floor(value / 3600000);
value = value % 3600000;
const minutes = Math.floor(value / 60000);
value = value % 60000;
const seconds = Math.floor(value / 1000);
return (days ? days + " days " : "") +
(hours ? hours + " hours " : "") +
(minutes ? minutes + " minutes " : "") +
(seconds ? seconds + " seconds " : "") +
(!days && !hours && !minutes && !seconds ? 0 : "");
}
}

Categories

Resources