Как прочитать правильные значения времени/продолжительности из таблицы Google

Я пытаюсь получить от форматированного по времени Cell (hh: mm: ss) значение часа, значения могут быть больше 24:00:00, например 20000: 00: 00 должны давать 20000:

Таблица:

two Google Spread Sheet

если вы прочитали значение E1:

var total = sheet.getRange("E1").getValue();
Logger.log(total);

Результат:

Сб Апр 12 07:09:21 GMT + 00: 09 1902

Теперь я попытался преобразовать его в объект Date и получить временную метку Unix:

  var date = new Date(total);
  var milsec = date.getTime();
  Logger.log(Utilities.formatString("%11.6f",milsec));
  var hours = milsec / 1000 / 60 / 60; 
  Logger.log(hours)

+1374127872020,000000

+381702,1866722222

Вопрос в том, как получить правильное значение 20000?

Ответ 1

Для будущих читателей. Существуют две новые функции getDisplayValue() и getDisplayValues(), предоставляемые App Script людьми, которые возвращают отображаемое значение. Ознакомьтесь с документацией здесь

Ответ 2

Развернувшись на том, что сделал Серж, я написал некоторые функции, которые нужно немного читать и учитывать разницу в часовых поясах между электронной таблицей и script.

function getValueAsSeconds(range) {
  var value = range.getValue();

  // Get the date value in the spreadsheet timezone.
  var spreadsheetTimezone = range.getSheet().getParent().getSpreadsheetTimeZone();
  var dateString = Utilities.formatDate(value, spreadsheetTimezone, 
      'EEE, d MMM yyyy HH:mm:ss');
  var date = new Date(dateString);

  // Initialize the date of the epoch.
  var epoch = new Date('Dec 30, 1899 00:00:00');

  // Calculate the number of milliseconds between the epoch and the value.
  var diff = date.getTime() - epoch.getTime();

  // Convert the milliseconds to seconds and return.
  return Math.round(diff / 1000);
}

function getValueAsMinutes(range) {
  return getValueAsSeconds(range) / 60;
}

function getValueAsHours(range) {
  return getValueAsMinutes(range) / 60;
}

Вы можете использовать следующие функции:

var range = SpreadsheetApp.getActiveSheet().getRange('A1');
Logger.log(getValueAsHours(range));

Излишне говорить, что это большая работа, чтобы получить количество часов из диапазона. Пожалуйста, звездочка Проблема 402, которая является запросом функции, чтобы иметь возможность получить буквальное строковое значение из ячейки.

Ответ 3

Значение, которое вы видите (Sat Apr 12 07:09:21 GMT + 00: 09 1902), является эквивалентной датой в стандартном времени Javascript, что на 20000 часов позже даты ref.

следует просто удалить эталонное значение электронной таблицы из вашего результата, чтобы получить то, что вы хотите.

Этот код выполняет трюк:

function getHours(){
  var sh = SpreadsheetApp.getActiveSpreadsheet();
  var cellValue = sh.getRange('E1').getValue();
  var eqDate = new Date(cellValue);// this is the date object corresponding to your cell value in JS standard 
  Logger.log('Cell Date in JS format '+eqDate)
  Logger.log('ref date in JS '+new Date(0,0,0,0,0,0));
  var testOnZero = eqDate.getTime();Logger.log('Use this with a cell value = 0 to check the value to use in the next line of code '+testOnZero);
  var hours = (eqDate.getTime()+ 2.2091616E12 )/3600000 ; // getTime retrieves the value in milliseconds, 2.2091616E12 is the difference between javascript ref and spreadsheet ref. 
  Logger.log('Value in hours with offset correction : '+hours); // show result in hours (obtained by dividing by 3600000)
}

enter image description here

Примечание: этот код получает только часы, если у вас будут минуты и/или секунды, тогда он должен быть разработан, чтобы справиться с этим... сообщите нам, если вам это нужно.


EDIT: слово объяснения...

В таблицах используется контрольная дата 12/30/1899, в то время как Javascript использует 01/01/1970, это означает, что между обеими ссылками есть разница 25568 дней. Все это предполагает, что мы используем один и тот же часовой пояс в обеих системах. Когда мы преобразуем значение даты в электронную таблицу в объект даты javascript, механизм GAS автоматически добавляет разницу, чтобы сохранить согласованность между датами.

В этом случае мы не хотим знать реальную дату чего-то, а скорее абсолютное значение часов, т.е. "продолжительность", поэтому нам нужно удалить смещение дня 25568. Это делается с помощью метода getTime(), который возвращает миллисекунды, отсчитанные с датой ссылки JS, единственное, что нам нужно знать, это значение в миллисекундах контрольной даты электронной таблицы и вычесть это значение из фактического объекта даты. Затем немного математики, чтобы получить часы вместо миллисекунд, и мы закончили.

Я знаю, что это кажется немного сложным, и я не уверен, что моя попытка объяснить действительно прояснит вопрос, но всегда стоит попробовать, не так ли?

В любом случае результат - это то, что нам нужно, пока (как указано в комментариях) отрегулируйте значение смещения в соответствии с настройками часового пояса электронной таблицы. Разумеется, можно было бы автоматически использовать дескриптор script, но это сделало бы script более сложным, не уверенным, что это действительно необходимо.

Ответ 4

Для простых электронных таблиц вы можете изменить часовой пояс электронной таблицы на GMT без летнего времени и использовать эту короткую функцию преобразования:

function durationToSeconds(value) {
  var timezoneName = SpreadsheetApp.getActive().getSpreadsheetTimeZone();
  if (timezoneName != "Etc/GMT") {
    throw new Error("Timezone must be GMT to handle time durations, found " + timezoneName);
  }
  return (Number(value) + 2209161600000) / 1000;
}

Ответ Эрика Коледы во многом более общий. Я написал это, пытаясь понять, как он обрабатывает угловые случаи с часовым поясом электронной таблицы, часовым поясом браузера и изменениями часового пояса в 1900 году на Аляске и Стокгольме.