Averaging Times using Javascript

2019-07-18 07:50发布

问题:

I am building an app using Phonegap and JQuery.

The app stores ( using window.localStorage ) a set of times (no more than 10) in the format.

    HH:MM:SS.mm

There are a number of 'Zero' times in the list eg '00:00:00.00' which iphonegap, javascript eliminate using..

    function removeA(arr){
        var what, a= arguments, L= a.length, ax;
        while(L> 1 && arr.length){
            what= a[--L];
            while((ax= arr.indexOf(what))!= -1){
                arr.splice(ax, 1);
            }
        }
        return arr;
    }

    scores.sort();
    removeA(scores,'00:00:00.00');

so that i'm left with the fastest time first, and only the times that have a value.

I need to produce from the remaining values the average of those times.

eg:  00:00:03.00
     00:00:05.00
     00:00:02.00
     00:00:06.00

=    00:00:04.00

thanks in advance :)

回答1:

var times= [ '00:00:03.00', '00:00:05.00', '00:00:02.00', '00:00:06.00'],
    date = 0,
    result = '';
function offsetify(t){
    return t < 10 ? '0' + t : t;
}
for(var x = 0; x < times.length; x++ ) {
    var tarr = times[x].split(':');
    date += new Date(0, 0, 0, tarr[0], tarr[1], tarr[2].split('.')[0], tarr[2].split('.')[1]).getTime();   
}
var avg = new Date(date/times.length);
result = offsetify(avg.getHours()) + ':' + offsetify(avg.getMinutes()) + ':' + offsetify(avg.getSeconds()) + '.' + offsetify(avg.getMilliseconds());

DEMO



回答2:

if you are going to also have millisecond values and you want to consider them, then convert the times into millisecond. Now, add them and divide them by the number of records. Else, convert everything to seconds and find the average - you get the answer in seconds, of course.

The conversion is quite simple if take little time to think over it. Here's how to convert.

To milliseconds:

function convertToMS(timeStr) {      // timeStr in format 'HH:MM:SS.mm'
    var I = parseInt;  // for brevity
    var t = timeStr,
        h = I( t.substr(0,2) ),
        m = I( t.substr(3,2) ),
        s = I( t.substr(6,2) ),
        ms = I( t.substr(9,2) );

    return h * 3600000 + m * 60000 + s * 1000 + ms;
}

To seconds:

function convertToS(timeStr) {      // timeStr in format 'HH:MM:SS[.mm]'  -- .mm is ignored.
    var I = parseInt;  // for brevity
    var t = timeStr,
        h = I( t.substr(0,2) ),
        m = I( t.substr(3,2) ),
        s = I( t.substr(6,2) );

    return h * 3600 + m * 60 + s;
}

After the conversion's done, add them up and find the average.

UPDATE: To convert back to the format 'HH:MM:SS.mm', we change back the time into 'chunks' of hours, minutes, seconds and (if applicable) milliseconds.

function chunkifyFromSec(time) {  // time in s
    var t = "",
        h = Math.floor(time / 3600),
        m = Math.floor( (t - (h * 3600)) / 60 ),
        s = t - (h * 3600) - (m * 60);
    return {
        HH: h, MM: m, SS: s, mm: 0
    };
}
function chunkifyFromMS(time) {   // time in ms
    var t = "",
        h = Math.floor(time / 3600000),
        m = Math.floor( (t - (h * 3600000)) / 60000 ),
        s = Math.floor( (t - (h * 3600000) - (m * 60000)) / 1000 ),
        mm = t - (h * 3600000) - (m * 600000) - (s * 1000);
    return {
        HH: h, MM: m, SS: s, mm: mm
    };
}

Then, we return the string in the format 'HH:MM:SS.mm' using this:

function toTimeStr(chunks) {
    return
           (chunks.HH < 0 ? '0' : '') + chunks.HH + ":"
           += (chunks.MM < 0 ? '0' : '') + chunks.MM + ":"
           += (chunks.SS < 0 ? '0' : '') + chunks.SS + "."
           += (chunks.mm < 0 ? '0' : '') + chunks.mm
}


回答3:

To return the answer in milliseconds or seconds:

var times = ["00:00:03.00", "00:00:05.00", "00:00:02.00", "00:00:06.00"];

function averageTimes(times,unit) {
    if (!times) {
        return false;
    }
    else {
        var totalMilliseconds = 0, hours, minutes, seconds, milliseconds, parts;
        for (var i = 0, len = times.length; i < len; i++) {
            parts = times[i].split(':');
            hours = parseInt(parts[0], 10) * 3600000;
            minutes = parseInt(parts[1], 10) * 60000;
            seconds = parseInt(parts[2].split('.')[0], 10) * 1000;
            milliseconds = parseInt(parts[2].split('.')[1], 10);
            totalMilliseconds += (hours + minutes + seconds + milliseconds);
        }
        if (!unit || unit.toLowerCase() == 'ms'){
            return totalMilliseconds/times.length + ' milliseconds';
        }
        else if (unit.toLowerCase() == 's') {
            return (totalMilliseconds/1000)/times.length + ' seconds';
        }

    }
}

// parameters:
// times: an array of times in your supplied format, 'HH:MM:SS:mm',
// unit: a string ('ms' or 's'), denoting whether to return milliseconds or seconds.
var average = averageTimes(times,'s');
console.log(average);​

JS Fiddle demo.

References:

  • for(){/*...*/} loop.
  • parseInt().
  • split().
  • toLowerCase().


回答4:

I don't have much experience with Javascript so I might have some syntax errors but I think you could do something like

var i = 0;
var totalTime = 0.0;
for (i=0; i < scores.length; i++) {
    var hours = parseFloat(scores[i].substring(0, 2)); //get numeric value for hours
    var minutes = parseFloat(scores[i].substring(3,5)); //get numeric value for minutes
    var seconds = parseFloat(scores[i].substring(6)); //get numeric for the seconds

    var time = ((hours * 60) + minutes) * 60 + seconds; //60 minutes in an hour, 60 seconds in a minute
    totalTime += time;
}

var avgTime = totalTime/scores.length;

var avgHours = Math.floor(avgTime / 3600); //60*60
var avgHoursStr = String(avgHours);

var avgMinutes = Math.floor((avgTime % 3600) / 60); //mod to get rid of the hours
var avgMinutesStr = String(avgMinutes);

var avgSeconds = avgTime - avgHours*3600 - avgMinutes*60; //get the remainder. Can't use mod due to decimal
var avgSeconds = String(avgSeconds);

//Concat strings. Add the ":" spacers. Where necessary, add leading 0
var avgStr = (avgHoursStr.length > 1 ? "" : "0") + avgHoursStr + ":" + (avgMinutesStr.length > 1 ? "" : "0") + avgMinuteStr + ":" + avgSecondsStr;

[EDIT - Thanks to Parth Thakkar for point out my problem]