I want to convert this:
00:07:57,685
to seconds.
It should return 00*60 + 07*60 + 57,685
The problem is its format I did not manage to write an optimized function.
const input = "00:07:57,685";
const [hours, minutes, secondsRaw] = input.split(/:/g);
const seconds = secondsRaw.replace(",", ".");
let output = 0;
output += parseInt(hours) * 3600;
output += parseInt(minutes) * 60;
output += parseFloat(seconds);
console.log(`${output} seconds`);
Here is a working sample :
function stringTimeToSecond (stringTime) {
// convert from "," float notation to "." float notation
// split your string to [h, m, s]
// reverse to get [s, m, h] to be able to use indice on the reduce method
const stringTimeArray = stringTime.replace(',','.').split(":").reverse();
// 60^0 = 1 for seconds
// 60^1 = 60 for minutes
// 60^2 = 3600 for hours
return stringTimeArray.reduce((timeInSecond, time, i) => {
timeInSecond += time * Math.pow(60, i);
return timeInSecond;
}, 0);
}
Reduce method will iterate through your array and then return your accumulator "timeInSecond". The accumulator is initialized to 0 as the second argument of the reduce function.
I think this might work if i understood your question right:
let timestamp = "00:07:57,685"
let seconds = timestamp.split(":")[2].split(",")[0]
Related
I got my first touch with js yesterday and i got this small task to do a small script in bulding controller. I am reading values from certain location and calculating energy, and after 1 hour I should read the same values and subtract them to get get delta energy delta. The script should run constantly so Im using while(1) sleep(3,6 * 1000000)
Here is my code where I'm at
function summa() {
var E1 = (parseFloat(read("location1","value1")) *
parseFloat(read("location11","value11"))) / Math.pow(10,6)
executePropertyCommand("object1","Value","Write", E1)
var E2 = (parseFloat(read("location2","value2")) *
parseFloat(read("location22","value22"))) / Math.pow(10,6)
executePropertyCommand("object2","Value","Write", E2)
var IT_Sum = (E1 + E2)
return IT_Sum}
setTimeout(summa1,3.599 * 1000000);{
function summa1() {
var E1 = (parseFloat(read("location1","value1")) *
parseFloat(read("location1","value1"))) / Math.pow(10,6)
var E2 = (parseFloat(read("location2","value2")) *
parseFloat(read("location22","value2"))) / Math.pow(10,6)
var IT_Sum1 = (E1 + E2)
return IT_Sum1 }}
while(1) {
var sum1 = summa()
var sum2 = summa1()
var IT_delta = summa2 - summa1
sleep(3.6 * 1000000)}
I've tried to locate the settimeout in different locations like into the while loop but i cant seem to get the sum2 to wait for the delay.
Any ideas for better way to calculate the subtraction of same data in 1 hour loops?
You can add values to the array every hour and then calculate the difference of adjacent indexes.
To run code every hour use window.setTimeout and pass callback and time.
// array with values added each hour
var numbers = [];
function runHourly() {
var dateNow = new Date();
var mins = dateNow.getMinutes();
var secs = dateNow.getSeconds();
var interval = (60*(60-mins)+(60-secs))*1000;
if (interval > 0) {
window.setTimeout(runHourly, interval);
}
// your code for calculating delta goes here
numbers.push(summa());
if(numbers.length >= 2) {
var IT_delta = numbers[1] - numbers[0];
// do something with delta here
// shift array for getting delta in an hour for new values…
numbers.shift();
}
}
I am looping through an array containing a number of objects and for each object I want to make a fetch which should return a time prediction based on information about the current object. I then want to add this time to a time variable that is declared outside the loop. In the example below I have two objects in the array. The first object returns a time of 34 and the second object returns a time of 72. However, when I check the time it is always only 72. Because of this I think the first might not be completing before the second one starts. The code looks as follows:
for (var l = 0; l < journeyArr.length; l++){
console.log("time at start of loop: ", time)
startStop = journeyArr[l].stops[0].id
endStop = journeyArr[l].stops[journeyArr[l].stops.length - 1].id
routeid = journeyArr[l].routeid
lineid = journeyArr[l].lineid
fetch("http://localhost:8000/routes/api/predict/?lineid="+lineid+"&start_stop="+startStop+"&end_stop="+endStop+"&routeid="+routeid+"&time_secs="+seconds+"&temp="+temp+"&rain=0.16&dow="+dayNum)
.then(response => {
return response.json()
})
.then(data => {
time += data.journey_info.journey_time.hours * 60
time += data.journey_info.journey_time.minutes
})
}
//Timeout just after the for loop to fetch times and to calculate
setTimeout(()=>{
var hours = Math.floor(time / 60);
var minutes = time % 60;
timeLeft.innerHTML = hours + " hour(s) " + minutes + " minutes";
},10000)
You can use async/await in this case. Put your code inside an async function, and trigger fetch by calling the function.
let fetchData = async () => {
let time = 0;
for (var l = 0; l < journeyArr.length; l++){
console.log("time at start of loop: ", time)
startStop = journeyArr[l].stops[0].id
endStop = journeyArr[l].stops[journeyArr[l].stops.length - 1].id
routeid = journeyArr[l].routeid
lineid = journeyArr[l].lineid
const response = await fetch("http://localhost:8000/routes/api/predict/?lineid="+lineid+"&start_stop="+startStop+"&end_stop="+endStop+"&routeid="+routeid+"&time_secs="+seconds+"&temp="+temp+"&rain=0.16&dow="+dayNum)
const data = response.json()
time += data.journey_info.journey_time.hours * 60
time += data.journey_info.journey_time.minutes
}
//Timeout just after the for loop to fetch times and to calculate
setTimeout(()=>{
var hours = Math.floor(time / 60);
var minutes = time % 60;
timeLeft.innerHTML = hours + " hour(s) " + minutes + " minutes";
},10000)
}
fetchData() // Trigger the fetch loop
You have to declare your Variables in the for loop, otherwise you overwrite their values all the time and only have the last one.
so replace:
startStop = journeyArr[l].stops[0].id
endStop = journeyArr[l].stops[journeyArr[l].stops.length - 1].id
routeid = journeyArr[l].routeid
lineid = journeyArr[l].lineid
with :
const startStop = journeyArr[l].stops[0].id
const endStop = journeyArr[l].stops[journeyArr[l].stops.length - 1].id
const routeid = journeyArr[l].routeid
const lineid = journeyArr[l].lineid
I have an array of time duration strings as below, and would like to find the minimum time.
group = ["41:04", "54:50", "01:03:50"] // note this is mix of **mm:ss** and **HH:mm:ss**
I am using moment:
group.map(tid => moment.duration(tid,'hh:mm:ss').asSeconds());
but it interprets the first two elements as "hh:mm" instead of "mm:ss", and results in:
[147840, 197400, 3830]
However, the first element "41:04" is the shortest time duration.
Is there any way to get this right using moment? Or what is the best way to find the minimum time duration?
Note that if i concatenate zeros to the string by myself (ie, 00:41:04), it will be correct.
You could calculate the seconds elapsed using simple mathematics without using any libraries.
For example;
41:04 = 41 * 60 + 04
01:03:50 = 01 * (60 ^ 2) + 03 * 60 + 50
Creating simple function to calculate seconds elapsed.
const getSeconds = str => {
const sp = str.split(":");
let sum = 0;
sp.map((d, k) => {
sum += Number(d) * 60 ** (sp.length - 1 - k);
});
return sum;
};
Now you could loop through your array to get the seconds.
const min = group.reduce((d, k) => {
const a = getSeconds(d),
b = getSeconds(k);
return a < b ? d : k;
});
As a whole you could check out the code snippet below;
const group = ["50:04","41:04", "54:50", "01:03:50"];
const getSeconds = str => {
const sp = str.split(":");
let sum = 0;
sp.map((d, k) => {
sum += Number(d) * 60 ** (sp.length - 1 - k);
});
return sum;
};
const min = group.reduce((d, k) => {
const a = getSeconds(d),
b = getSeconds(k);
return a < b ? d : k;
});
console.log(min);
There might be more elegant solutions. But this is what I came up with. :D
I have a timer app that counts time passed in milliseconds, converts that to a formatted string, then displays it. Elsewhere, I have a function that converts that same string to milliseconds for some other math I have to do. Seems counter-intuitive, I know, but it mostly works.
Anyways, this is the function that takes a string like 14.55 (14 seconds and ~550 milliseconds) and returns the time in milliseconds, but it's not doing it right.
function toMS(str) {
if(str.includes(":")) {
const [mins, secms] = str.split(":");
const [sec, ms] = secms.split(".");
return ((+mins * 60) + +sec) * 1000 + +ms;
} else {
const [sec, ms] = str.split(".");
return (+sec) * 1000 + +ms;
}
}
If I pass in something like 10.77, it returns 10077 instead of 10770 like it should. What's wrong with it?
Why don't you use parseFloat?
function toMS(str) {
if(str.includes(":")) {
const [mins, secms] = str.split(":");
const sec = parseFloat(secms);
return ((+mins * 60) + sec) * 1000;
} else {
return parseFloat(str) * 1000;
}
}
0.1 seconds is equal to 100 ms, not 1ms. Remember that 0.1s can be also written as 1/10 of a second, 1/10 * 1000ms = 100ms.
It means that you have to multiplicate the decimal part for 100 in order to get the correct result.
function toMS(str) {
if(str.includes(":")) {
const [mins, secms] = str.split(":");
const [sec, ms] = secms.split(".");
return ((+mins * 60) + +sec) * 1000 + +ms;
} else {
const [sec, ms] = str.split(".");
return (+sec) * 1000 + ms * 100;
}
}
Note: You don't need the + to convert your variable, since the * is enough to coerce it to number.
You can also apply the DRY principle in this way:
function toMS(str) {
let mins = 0;
if(str.includes(":")) {
[mins, str] = str.split(":");
}
const [sec, ms] = str.split(".");
return mins * 60000 + sec * 1000 + ms * 100;
}
If you're worried about rounding errors with the parseFloat solution here's a pure string implementation:
ms = +(ms.concat("00").substring(0,3));
So, what are we doing?
Pad the millisecond string with "0". We pad with 2 zeros to cater for the following situations:
a. There are more than 3 digits - in which case all the padded zeros will be ignored later
b. There are exactly 3 digits - all the padded zeros will be ignored later
c. There are exactly 2 digits - the extra zero will be ignored
d. There is exactly 1 digit - both zeros are needed
e. There are no digits at all - both zeros will be converted to 0 later
We take only the first 3 digits. This will automatically ignore both the case of any extra zeros and if ms was accidentally specified with more accuracy than required (eg. if someone entered 1.1234)
We convert to number using the unary + operator
This is my array. Its length is about 9000. This is what a small bit of it looks like:
foreach_arr = ["21:07:01.535", "21:07:01.535", "21:07:26.113"]
There are a few occurences where the times diff is greater than a minute, and that is when I want to grab those times. And later use those times to get certain indices from another array. i.e "array"
I'm also using moment.js for time parsing.
Expected result: array = [8127, 9375, 13166, 14182]
Actual result: array = [8127, 13166]
Can't seem to find the issue here, I am getting 2 results when im supposed to be getting 4.
If the whole array is needed for troubleshooting, ill add it if I can.
var xx = foreach_arr.length - 1;
for(var z = 0; z < xx; z++) {
var current_row = foreach_arr[z];
var next_row = foreach_arr[z + 1];
var msElapsedTime = moment(next_row,"HH:mm:ss.SSS").diff(moment(current_row, "HH:mm:ss.SSS")) / 1000;
if(msElapsedTime > 60) {
attempt_indices.push(foreach_arr[z]);
}
}
for(var x = 0; x < attempt_indices.length; x++) {
array.push(newdata.indexOf(attempt_indices[x]));
}
Since the OP doesn't really need my code anymore, I'm posting it here to remove the downvote as much as anything else :)
const foreach_arr = ["21:07:01.535", "21:07:01.535", "21:07:26.113", '22:01:01.000'];
let processedForeach_arr = [];
let gtOneMinuteDiff = [];
foreach_arr.forEach((elem1, index1) => {
// elem1.split(':') turns foreach_arr[0] into ['21', '07', '01.535']
const splitElementArray = elem1.split(':');
let timeInMs = 0;
// this changes ['21', '07', '01.535'] into [75600000, 420000, 1535]
splitElementArray.forEach((elem2, index2) => {
if (index2 === 0) { // elem2 is hours. 3.6M ms per hour.
timeInMs += parseFloat(elem2) * 60 * 60 * 1000;
} else if (index2 === 1) { // elem2 is minutes. 60K ms per minute.
timeInMs += parseFloat(elem2) * 60 * 1000;
} else if (index2 === 2) { // elem2 is seconds. 1K ms per second.
timeInMs += parseFloat(elem2) * 1000;
} else {
throw `Expected array element formatted like HH:MM:SS.ms. Error on
element ${elem1}.`;
}
});
processedForeach_arr.push(timeInMs);
let timeDiff = processedForeach_arr[index1 - 1] - processedForeach_arr[index1];
if (Math.abs(timeDiff) > 60000) {
gtOneMinuteDiff.push(timeDiff);
}
});
To get the difference in milliseconds between foreach_arr[n] and foreach_arr[n+1], this code will
split each element of foreach_arr into 3 strings (hours, minutes, and seconds + milliseconds)
run parseFloat on each of those values to convert them to a number
convert all numbers to milliseconds and add them together
compare each consecutive value and return the difference.
Ok, I got this far and my son needs me. I'll finish out the code asap but you might beat me to it, hopefully the instructions above help.
turns out my code wasn't wrong. Just my idea of the whole proccess.
array = [8127, 13166]
is what I initialy get. With this, I use indexOf on my other array to eventually get my array as expected:
var another_test_arr = [];
for(var v = 0; v < array.length ; v++) {
var find = foreach_arr.indexOf(attempt_indices[v]);
another_test_arr.push(array[v], newdata.indexOf(foreach_arr[find + 1]));
}
Result: array = [8127, 9375, 13166, 14182]