2
votes

I have a Google Sheet with three columns: - Date and time (timestamp) - Duration - Description

I have an script that when I write something in 'Description', inserts in 'Date' the date and time at this moment, and the 'Duration':

function onEdit(e) {
  if(e.source.getActiveSheet().getName() == "Sheet2" ) {
    var col = e.source.getActiveCell().getColumn();
    if(col == 3 ) {
      // I'm in column three
      var cellTimeStamp = e.range.offset(0,-2); // First column of the same row
      var cellTimeDiff = e.range.offset(0,-1); // Second column of the same row
      var cellTimePrev = e.range.offset(-1,-2); // First column of the previous row

      var timeTimeStamp = new Date();
      var iniTime = cellTimePrev.getValue().getTime();
      var finTime = timeTimeStamp.getTime() ;
      var timeDiff = String(finTime - iniTime) ;


      cellTimeStamp.setValue(timeTimeStamp);  

      cellTimeDiff.setValue(timeDiff); // [***]


    }
  }    
}

When this executes (as an event) in the column of 'Duration' there is NOT something in the format of 'HH:mm:ss'.

But if I remove the last line in this script and adds this formulae in the sheet: =A3-A2 (in row 3) =A4-A3 (in row 4) ... then it works ok.

I'd like to know how to meet the same result but with a script.

Thanks in advance.

1
Just a note, the format for a duration is [hh]:mm:ss. I don't think this has ever been written down, I had to get it by using range.getNumberFormat()Matt
It is source code in a Google Spreadsheet. Now I use a formulae (=A4-A3), not the source code in this solution.Jose Luis
My formula still subtracts two date times, but originally I was formatting the output cell with hh:mm:ss which was fine providing the difference was under a day. I had to figure out how to show the duration once the differences exceeded a day. I wish Google would just document Range::setNumberFormat()...Matt

1 Answers

2
votes

timeDiff is the result of finTime - iniTime which are both native date object values, which means we have milliseconds .

converting that in hh:mm:ss is simple math... : 60 seconds in a minute and 60 minutes in an hour... A simple code could be like this :

function msToTime(s) {
  var ms = s % 1000;
  s = (s - ms) / 1000;
  var secs = s % 60;
  s = (s - secs) / 60;
  var mins = s % 60;
  var hrs = (s - mins) / 60;

  return hrs + ':' + mins + ':' + secs; // milliSecs are not shown but you can use ms if needed
}

If you prefer formating your string more conventionally (2 digits for each value) don't forget you can use Utilities.formatString() to do so.

example below :

  return Utilities.formatString("%02d",hrs) + ':' + Utilities.formatString("%02d",mins) + ':' + Utilities.formatString("%02d",secs);

EDIT

Following your comment :

Spreadsheets are smarter than you think, you can try the code below and you will see that the result is actually a time value.(check by double clicking on it)

function test() {
  var sh = SpreadsheetApp.getActiveSheet();
  var t1 = sh.getRange('a1').getValue().getTime();
  var t2 = sh.getRange('b1').getValue().getTime();
  sh.getRange('c1').setValue(msToTime(t1-t2)).setNumberFormat('hh:mm:ss');

}

function msToTime(s) {
  var ms = s % 1000;
  s = (s - ms) / 1000;
  var secs = s % 60;
  s = (s - secs) / 60;
  var mins = s % 60;
  var hrs = (s - mins) / 60;

  return hrs + ':' + mins + ':' + secs; // milliSecs are not shown but you can use ms if needed
}

note that setNumberFormat('hh:mm:ss') is optional, it's only there to force the spreadsheet to display hour:min:sec format but automatic mode works as well.

enter image description here