Ответ 1
Для будущих читателей. Существуют две новые функции getDisplayValue()
и getDisplayValues()
, предоставляемые App Script людьми, которые возвращают отображаемое значение. Ознакомьтесь с документацией здесь
Я пытаюсь получить от форматированного по времени Cell (hh: mm: ss) значение часа, значения могут быть больше 24:00:00, например 20000: 00: 00 должны давать 20000:
Таблица:
если вы прочитали значение 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?
Для будущих читателей. Существуют две новые функции getDisplayValue()
и getDisplayValues()
, предоставляемые App Script людьми, которые возвращают отображаемое значение. Ознакомьтесь с документацией здесь
Развернувшись на том, что сделал Серж, я написал некоторые функции, которые нужно немного читать и учитывать разницу в часовых поясах между электронной таблицей и 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, которая является запросом функции, чтобы иметь возможность получить буквальное строковое значение из ячейки.
Значение, которое вы видите (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)
}
Примечание: этот код получает только часы, если у вас будут минуты и/или секунды, тогда он должен быть разработан, чтобы справиться с этим... сообщите нам, если вам это нужно.
EDIT: слово объяснения...
В таблицах используется контрольная дата 12/30/1899, в то время как Javascript использует 01/01/1970, это означает, что между обеими ссылками есть разница 25568 дней. Все это предполагает, что мы используем один и тот же часовой пояс в обеих системах. Когда мы преобразуем значение даты в электронную таблицу в объект даты javascript, механизм GAS автоматически добавляет разницу, чтобы сохранить согласованность между датами.
В этом случае мы не хотим знать реальную дату чего-то, а скорее абсолютное значение часов, т.е. "продолжительность", поэтому нам нужно удалить смещение дня 25568. Это делается с помощью метода getTime()
, который возвращает миллисекунды, отсчитанные с датой ссылки JS, единственное, что нам нужно знать, это значение в миллисекундах контрольной даты электронной таблицы и вычесть это значение из фактического объекта даты. Затем немного математики, чтобы получить часы вместо миллисекунд, и мы закончили.
Я знаю, что это кажется немного сложным, и я не уверен, что моя попытка объяснить действительно прояснит вопрос, но всегда стоит попробовать, не так ли?
В любом случае результат - это то, что нам нужно, пока (как указано в комментариях) отрегулируйте значение смещения в соответствии с настройками часового пояса электронной таблицы. Разумеется, можно было бы автоматически использовать дескриптор script, но это сделало бы script более сложным, не уверенным, что это действительно необходимо.
Для простых электронных таблиц вы можете изменить часовой пояс электронной таблицы на 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 году на Аляске и Стокгольме.