seconds to "DD:HH:mm:ss" with moment() [duplicate] - javascript

This question already has an answer here:
How to use moment.js to get remaining hours, minutes, and seconds from a unix timestamp?
(1 answer)
Closed 2 years ago.
I am trying to convert seconds to DD:HH:mm:ss format or other formats like (YYYYMMDD)
function secToFormat(seconds, format){
return moment.utc(seconds * 1000).format(format);
}
// works well.
console.log(secToFormat(40,"HH:mm:ss"));
console.log(secToFormat(100,"HH:mm:ss"));
console.log(secToFormat(1800,"HH:mm:ss"));
console.log(secToFormat(18800,"HH:mm:ss"));
console.log(secToFormat(86300,"HH:mm:ss"));
// doesn't work I expected.
console.log(secToFormat(40,"DD:HH:mm:ss")); //it returns 01:00:00:40 but I expect 00:00:00:40
console.log(secToFormat(100,"DD:HH:mm:ss")); //it returns 01:00:01:40 but I expect 00:00:01:40
console.log(secToFormat(86300,"DD:HH:mm:ss")); //it returns 01:23:58:20 but I expect 00:23:58:20
console.log(secToFormat(86400*2,"DD:HH:mm:ss")); //it returns 03:00:00:00 but I expect 02:00:00:00
// it also doesn't work with another format.
console.log(secToFormat(40, "MM:DD:HH:mm:ss")); // I want to get 00:00:00:00:40
console.log(secToFormat(100, "MM:DD:HH:mm:ss")); // I want to get 00:00:00:01:40
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.26.0/moment.min.js"></script>
I understand why it happens because it starts at 1970-01-01 00:00:00.
but I want to edit it what I expect.
How can I achieve it?

You can use moment.js' durations, however they don't have much in the way of formatting, e.g.
let seconds = 28763827;
let duration = moment.duration(seconds, 'seconds');
console.log('Default ISO: ' + duration); // "PT7989H57M7S"
console.log('Moment humanized: ' + duration.humanize()); // a year
console.log('Moment days: ' + duration.asDays()); // 332.91466435185185
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.26.0/moment.min.js"></script>
Consider writing your own function to convert to a format like d.HH:mm:ss, e.g.
function secsToTime(secs) {
let d = secs / 8.64e4 | 0;
let H = (secs % 8.64e4) / 3.6e3 | 0;
let m = (secs % 3.6e3) / 60 | 0;
let s = secs % 60;
let z = n=> (n < 10? '0' : '') + n;
return `${d}.${z(H)}:${z(m)}:${z(s)}`
}
let seconds = 28763827;
console.log(secsToTime(seconds));

Using moment-duration-format to implement.
It is actually the "officially referenced" way (by momentjs author in both issues and docs). Explanation and examples here in my other answer:
How to use moment.js to get remaining hours, minutes, and seconds from a unix timestamp?
#RobG's answer is a great base for rolling your own, and I am tempted to edit it into my answer in above link. But note that moment-duration-format already exists and is the sanctioned way to do it, as well as being an actively updated library, and really satisfies most any use case I can think of (eg: drop-in one statement replacement in OP's example code).
It is also possible to extract the data directly from duration's internal variable _data. Though, I really don't recommend doing that. I have a rough demo of that in the other answer.
function secToFormat(seconds, format){
return moment.duration(seconds,'seconds').format(format, {trim: false});
// trim: false so it doesn't trim off 0 values
// (so last one would be 01:40 instead of 00:00:00:01:40 if trim: true)
}
// works well.
console.log(secToFormat(40,"HH:mm:ss"));
console.log(secToFormat(100,"HH:mm:ss"));
console.log(secToFormat(1800,"HH:mm:ss"));
console.log(secToFormat(18800,"HH:mm:ss"));
console.log(secToFormat(86300,"HH:mm:ss"));
// doesn't work I expected.
console.log(secToFormat(40,"DD:HH:mm:ss")); //it returns 01:00:00:40 but I expect 00:00:00:40
console.log(secToFormat(100,"DD:HH:mm:ss")); //it returns 01:00:01:40 but I expect 00:00:01:40
console.log(secToFormat(86300,"DD:HH:mm:ss")); //it returns 01:23:58:20 but I expect 00:23:58:20
console.log(secToFormat(86400*2,"DD:HH:mm:ss")); //it returns 03:00:00:00 but I expect 02:00:00:00
// it also doesn't work with another format.
console.log(secToFormat(40, "MM:DD:HH:mm:ss")); // I want to get 00:00:00:00:40
console.log(secToFormat(100, "MM:DD:HH:mm:ss")); // I want to get 00:00:00:01:40
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.26.0/moment.min.js"></script>
<!-- moment-duration-format plugin -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-duration-format/2.3.1/moment-duration-format.min.js"></script>

Related

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.

Milliseconds passed since last minute in javascript

I'm probably just tired and not thinking clearly, but can someone give a concise way of getting the number of milliseconds passed since the last minute using javascript?
Something like Date.getSeconds(), but that would return milliseconds.
Although I could just do (Date.getSeconds()*1000) + Date.getMilliseconds(), this just seems really awkward and like there has to be a better way.
Thanks!
Depends what you're trying to do.
The difference between now and 1 minute ago in milliseconds should always be 60000 milliseconds. o_O
As Jan said Date.now() will return the current timestamp in milliseconds.
But it seems you might be looking for the getTime method, e.g.:
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Date/getTime
// note the keyword "new" below
var date_instance = new Date();
// separate example in case you're managing Date()'s and not the method,
// who knows, just an example
var timestamp = date_instance.getTime();
var minute_before_timestamp = function(ts){
return ts - 60000;
};
console.log(minute_before_timestamp(timestamp));
console.log(minute_before_timestamp(date_instance.getTime()); // always same as above!
// or use the current time
console.log(minute_before_timestamp(Date.now()));
console.log(minute_before_timestamp(new Date().getTime()));
(another useful link: http://www.epochconverter.com/)
What about…
Date.now() % 60000
Date.now returns the current UNIX timestamp in ms.
To clarify what's happening there, the % operator is called modulo and what it does is that it gives you the remainder from dividing the first number by the other one.
An example can be:
20 % 7 === 6
13 % 7 === 6
6 % 7 === 6
…because…
20 / 7 = 2 + 6 / 7
13 / 7 = 1 + 6 / 7
6 / 7 = 0 + 6 / 7
(note the remainder 6)

PHP, javascript, jquery, setting hour only

I have created a small function that i need on my site successfully in php. But i now realise i actually need this in javascript or jquery as PHP will only excute this code on load.. i need this function to work with onchange on a select. The code below is my function.. Can anyone point out where i start to convert this into js/jquery like code:
function setTrnTime ($hr, $journeyTime){
date_default_timezone_set('GMT');
//convert current hour to time format hour
$currentHour = (date("H", mktime($hr)));
// Journey time in hours
$journey = $journeyTime
$journey = $journey/60; // Get hours
$journey = ceil($journey); // Round off to next hour i.e. 3 hours 20mins is now 4 hours
// New Hours
$NewHour = (date("H", mktime($journey)));
$Newhour = $NewHour*60*60; // convert to seconds
// Final hour is Current Hour - JourneyTime (Hours)
$trnHour = (date('H', mktime($currentHour-$NewHour)));
return $trnHour;
}
With the code above, if i pass two values 06, 60: that would mean my answer would be 05. e.g. 06 is 6am. 60 is 60mins.. so 6am - 60mins = 5am.
You can do the same in javascript using the Date object, see info here
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date
EDITED: Added some code, also not even using the Date object.
But do you need something that complex, doesn't the following do what you are after with less steps.
http://jsfiddle.net/WWTDc/
If hr is a Date object, then it's very simple. Otherwise you can create a Date object and set its hour:
//! \param[in] hr Date object or hour (0--23)
//! \param[in] journeyTime journey time in minutes.
function setTrnTime(hr,journeyTime){
var end;
if(typeof(hr) === 'number'){
end = new Date();
end.setHours(hr);
}
else
end = hr;
return (new Date(end - journeyTime*60*1000)).getHours();
}
This will return the hour (demonstration).
See here for information about Date object in JavaScript.

Javascript Timestamp from ISO8061

I'm having a bit of an issue when dealing with getting a timestamp from an iso8061 date.
For some reason it work perfectly in Chrome, but causes an Invalid Date error in Firefox. The exact line is:
var date = new Date(time.replace(/-/g,"/").replace(/[TZ]/g," "));
I've tried passing the date through (as the var time) 2011-03-09T16:46:58+00:00, 2011-03-09T16:46:58+0000 and 2011-03-09T16:48:37Z as per the spec outlined http://www.jibbering.com/faq/#dates but I still can't seem to get it to work in firefox. In fact, the last method didn't work in either browser.
If anyone could help me turn this iso8061 date into a timestamp, that would be great.
Thanks,
Angelo R.
take a look at JavaScript ISO8601/RFC3339 Date Parser:
their code:
Date.prototype.setISO8601 = function(dString){
var regexp = /(\d\d\d\d)(-)?(\d\d)(-)?(\d\d)(T)?(\d\d)(:)?(\d\d)(:)?(\d\d)(\.\d+)?(Z|([+-])(\d\d)(:)?(\d\d))/;
if (dString.toString().match(new RegExp(regexp))) {
var d = dString.match(new RegExp(regexp));
var offset = 0;
this.setUTCDate(1);
this.setUTCFullYear(parseInt(d[1],10));
this.setUTCMonth(parseInt(d[3],10) - 1);
this.setUTCDate(parseInt(d[5],10));
this.setUTCHours(parseInt(d[7],10));
this.setUTCMinutes(parseInt(d[9],10));
this.setUTCSeconds(parseInt(d[11],10));
if (d[12]) {
this.setUTCMilliseconds(parseFloat(d[12]) * 1000);
}
else {
this.setUTCMilliseconds(0);
}
if (d[13] != 'Z') {
offset = (d[15] * 60) + parseInt(d[17],10);
offset *= ((d[14] == '-') ? -1 : 1);
this.setTime(this.getTime() - offset * 60 * 1000);
}
}
else {
this.setTime(Date.parse(dString));
}
return this;
};
and then you can use it this way:
var today = new Date();
today.setISO8601('2008-12-19T16:39:57.67Z');
probably not that comfortable, but you can rewrite this function, or write another one which will return date based on ISO-8601 format
The way that the Date constructor handles string arguments differs across browsers. As the first answer to this question points out, IE recognizes hyphens, but Firefox does not, as just one example.
It's probably best to use the constructor that expects individual date parts.

Categories

Resources