14

我试图从时间格式的单元格(hh:mm:ss)中获取小时值,这些值可以更大 24:00:00 例如 20000:00:00 应该给出 20000:

桌子:

两张谷歌电子表格

如果您阅读 E1 的值:

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

结果是:

4 月 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 的正确值?

4

5 回答 5

20

扩展 Serge 所做的工作,我编写了一些函数,这些函数应该更容易阅读,并考虑到电子表格和脚本之间的时区差异。

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

  // Get the date value in the spreadsheet's 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 加注星标,这是一项功能请求,可以从单元格中获取文字字符串值。

于 2013-07-18T15:09:50.067 回答
13

有两个新函数可以返回日期时间或任何getDisplayValue()getDisplayValues()您在电子表格上看起来完全一样的东西。在此处查看文档

于 2016-10-09T05:33:10.103 回答
11

您看到的值(Sat Apr 12 07:09:21 GMT+00:09 1902)是 Javascript 标准时间中的等效日期,比参考日期晚 20000 小时。

您应该简单地从结果中删除电子表格参考值以获得您想要的。

这段代码可以解决问题:

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)
}

在此处输入图像描述

注意:这段代码只有几个小时,如果你有几分钟和/或几秒钟,那么它也应该被开发来处理它......如果你需要它,请告诉我们。


编辑:解释一下...

电子表格使用 1899 年 12 月 30 日作为参考日期,而 Javascript 使用 1970 年 1 月 1 日,这意味着两个参考之间存在 25568 天的差异。所有这一切都假设我们在两个系统中使用相同的时区。当我们将电子表格中的日期值转换为 javascript 日期对象时,GAS 引擎会自动添加差异以保持日期之间的一致性。

在这种情况下,我们不想知道某物的真实日期,而是想知道绝对小时值,即“持续时间”,因此我们需要删除 25568 天的偏移量。这是使用getTime()返回从 JS 引用日期开始计算的毫秒数的方法完成的,我们唯一需要知道的是电子表格引用日期的毫秒值,并从实际日期对象中减去该值。然后进行一些数学运算来获得几小时而不是毫秒,我们就完成了。

我知道这似乎有点复杂,我不确定我的解释是否会真正澄清问题,但总是值得尝试不是吗?

无论如何,只要(如评论中所述)根据电子表格的时区设置调整偏移值,结果就是我们需要的。当然可以让脚本自动处理它,但它会使脚本更加复杂,不确定它是否真的有必要。

于 2013-07-18T07:07:05.227 回答
5

对于简单的电子表格,您可以在没有夏令时的情况下将电子表格时区更改为 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;
}

Eric Koleda 的回答在许多方面更为笼统。我写这篇文章时试图了解它如何处理电子表格时区、浏览器时区以及 1900 年阿拉斯加和斯德哥尔摩的时区变化的极端情况。

于 2015-04-20T19:44:00.533 回答
0

在某处创建一个持续时间值为“00:00:00”的单元格。该单元格将用作参考。可能是隐藏单元格,也可能是具有配置值的不同工作表中的单元格。例如如下:

在此处输入图像描述

然后编写一个带有两个参数的函数 - 1)您要处理的值,以及 2)“00:00:00”的参考值。例如:

function gethours(val, ref) {

  let dv = new Date(val)
  let dr = new Date(ref)

  return (dv.getTime() - dr.getTime())/(1000*60*60)

}

由于 Sheets 对 Duration 类型所做的任何事情对两者来说都是完全相同的,我们现在可以将它们转换为 Dates 并减去,这会给出正确的值。在上面的代码示例中,我使用了 .getTime() ,它给出了自 1970 年 1 月 1 日以来的毫秒数,...。

如果我们试图计算该值到底发生了什么并进行更正,代码就会变得过于复杂。

一个警告:如果小时数非常大,比如 200,000:00:00,则会出现大量小数值,因为天/年不完全是 24 小时/365 天(?在这里推测)。具体来说,200000:00:00 结果为 200,000.16。

于 2021-09-02T16:10:31.123 回答