javascript 如何从 Google 电子表格中读取正确的时间/持续时间值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17715841/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to read the correct time/duration values from Google Spreadsheet
提问by patrick
I'm trying to get from a time formatted Cell (hh:mm:ss) the hour value, the values can be bigger 24:00:00 for example 20000:00:00 should give 20000:
我试图从时间格式的单元格 (hh:mm:ss) 中获取小时值,值可以更大 24:00:00 例如 20000:00:00 应该给 20000:
Table:
桌子:
if your read the Value of E1:
如果您阅读了 E1 的值:
var total = sheet.getRange("E1").getValue();
Logger.log(total);
The result is:
结果是:
Sat Apr 12 07:09:21 GMT+00:09 1902
4 月 12 日星期六 07:09:21 GMT+00:09 1902
Now I've tried to convert it to a Date object and get the Unix time stamp of it:
现在我尝试将其转换为 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
1374127872020.000000
381702.1866722222
The question is how to get the correct value of 20000 ?
问题是如何获得 20000 的正确值?
采纳答案by llaaalu
回答by Eric Koleda
Expanding on what Serge did, I wrote some functions that should be a bit easier to read and take into account timezone differences between the spreadsheet and the script.
扩展 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;
}
You can use these functions like so:
您可以像这样使用这些函数:
var range = SpreadsheetApp.getActiveSheet().getRange('A1');
Logger.log(getValueAsHours(range));
Needless to say, this is a lot of work to get the number of hours from a range. Please star Issue 402which is a feature request to have the ability to get the literal string value from a cell.
不用说,从一个范围内获取小时数需要做很多工作。请为问题 402 加星标,这是一项功能请求,可以从单元格中获取文字字符串值。
回答by Serge insas
The value you see (Sat Apr 12 07:09:21 GMT+00:09 1902) is the equivalent date in Javascript standard time that is 20000 hours later than ref date.
您看到的值 (Sat Apr 12 07:09:21 GMT+00:09 1902) 是 Javascript 标准时间中的等效日期,比参考日期晚 20000 小时。
you should simply remove the spreadsheet reference value from your result to get what you want.
您应该简单地从结果中删除电子表格参考值以获得您想要的结果。
This code does the trick :
这段代码可以解决问题:
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)
}
note : this code gets only hours , if your going to have minutes and/or seconds then it should be developped to handle that too... let us know if you need it.
注意:这段代码只有几个小时,如果你有几分钟和/或几秒钟的时间,那么它也应该被开发来处理……如果你需要它,请告诉我们。
EDIT : a word of explanation...
编辑:解释一下......
Spreadsheets use a reference date of 12/30/1899 while Javascript is using 01/01/1970, that means there is a difference of 25568 days between both references. All this assuming we use the same time zone in both systems. When we convert a date value in a spreadsheet to a javascript date object the GAS engine automatically adds the difference to keep consistency between dates.
电子表格使用 12/30/1899 的参考日期,而 Javascript 使用 01/01/1970,这意味着两个参考之间存在 25568 天的差异。所有这些都假设我们在两个系统中使用相同的时区。当我们将电子表格中的日期值转换为 javascript 日期对象时,GAS 引擎会自动添加差异以保持日期之间的一致性。
In this case we don't want to know the real date of something but rather an absolute hours value, ie a "duration", so we need to remove the 25568 day offset. This is done using the getTime()
method that returns milliseconds counted from the JS reference date, the only thing we have to know is the value in milliseconds of the spreadsheet reference date and substract this value from the actual date object. Then a bit of maths to get hours instead of milliseconds and we're done.
在这种情况下,我们不想知道某事的真实日期,而是想知道绝对小时值,即“持续时间”,因此我们需要删除 25568 天的偏移量。这是使用getTime()
返回从 JS 参考日期计算的毫秒数的方法完成的,我们唯一需要知道的是电子表格参考日期的毫秒值,并从实际日期对象中减去该值。然后进行一些数学运算来获得小时而不是毫秒,我们就完成了。
I know this seems a bit complicated and I'm not sure my attempt to explain will really clarify the question but it's always worth trying isn't it ?
我知道这看起来有点复杂,我不确定我的解释尝试是否真的能澄清问题,但它总是值得尝试,不是吗?
Anyway the result is what we needed as long as (as stated in the comments) one adjust the offset value according to the time zone settings of the spreadsheet. It would of course be possible to let the script handle that automatically but it would have make the script more complex, not sure it's really necessary.
无论如何,只要(如评论中所述)根据电子表格的时区设置调整偏移值,结果就是我们所需要的。当然可以让脚本自动处理,但它会使脚本更复杂,不确定它是否真的有必要。
回答by Tom Brown
For simple spreadsheets you may be able to change your spreadsheet timezone to GMT without daylight saving and use this short conversion function:
对于简单的电子表格,您可以在没有夏令时的情况下将电子表格时区更改为 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's answer is in many ways more general. I wrote this while trying to understand how it handles the corner cases with the spreadsheet timezone, browser timezone and the timezone changes in 1900 in Alaska and Stockholm.
Eric Koleda 的回答在很多方面都更为笼统。我写这篇文章时试图了解它如何处理电子表格时区、浏览器时区以及 1900 年阿拉斯加和斯德哥尔摩时区变化的极端情况。