1

Assuming the following:

  • There is a long-running server-side task which processes many records
  • The progress of the task is linear -- meaning that each record takes the same amount of time to process.
  • We have just used an AJAX request to find out from the server:
    1. The start time in UTC
    2. The total number of records to be processed
    3. The number of records that have already been processed

How can we calculate the remaining time for this process on the client-side using javascript?

Alex W
  • 37,233
  • 13
  • 109
  • 109
Eric Seastrand
  • 2,473
  • 1
  • 29
  • 36

1 Answers1

1

When I wasn't able to find a solution for this on StackExchange, I created one of my own.

function calculateSecondsRemaining(startUtc, completedTasks, totalTasks) {
    var timezoneOffsetMs = new Date().getTimezoneOffset() * 1000 * 60;

    var startDate = new Date(Date.parse(startUtc) - timezoneOffsetMs);

    var currentDate = new Date();

    var elapsed = currentDate - startDate;

    var timePer = elapsed / completedTasks;

    var tasksRemaining = totalTasks - completedTasks;

    var millisecondsRemaining = tasksRemaining * timePer;

    return millisecondsRemaining / 1000;
}

This function subtracts the browser's timezone offset, since it needs to accept a UTC date. You can call it like so:

calculateSecondsRemaining('2017-09-28T17:53:16', 2717, 8000);

It will give you an output like:

7158.334723592197

If you want a human-readable output, you can combine this with a function like the one in this StackExchange answer to get something like:

secondsToString(calculateSecondsRemaining('2017-09-28T17:53:16', 2717, 8000));
"0 years 0 days 1 hours 59 minutes 18.334723592197406 seconds"

The code for the secondsToString() function is provided below for reference:

function secondsToString(seconds) {
    var numyears = Math.floor(seconds / 31536000);
    var numdays = Math.floor((seconds % 31536000) / 86400); 
    var numhours = Math.floor(((seconds % 31536000) % 86400) / 3600);
    var numminutes = Math.floor((((seconds % 31536000) % 86400) % 3600) / 60);
    var numseconds = (((seconds % 31536000) % 86400) % 3600) % 60;
    return numyears + " years " +  numdays + " days " + numhours + " hours " + numminutes + " minutes " + numseconds + " seconds";
}
Eric Seastrand
  • 2,473
  • 1
  • 29
  • 36