我要做的就是这个。
比方说,在Google表格中,我有一个页面,其中包含以下列:
在I3列中,我的日期为11/30/19。 在J3栏中,我的今天是4/30/20。 我希望能够计算出这两个日期之间的差额,并告诉我自19/30/19以来已经有多少个月了。
当前,我认为代码可以正常工作,但是我得到的结果是:
[20-05-02 01:43:18:650 MDT] 5个月6天
[20-05-02 01:43:18:656 MDT] 5个月6天
[20-05-02 01:43:18:660 MDT] 5个月6天
但是日期计算仍然错误。例如,从2020年1月1日至1月25日,它显示5个月零6天。
我在过滤器1中的循环也只是在计算第一个可用日期,然后执行此操作三次,而不是转到下一个记录并进行计算。
到目前为止,我有以下代码:
function myFunction() {
}
var moment = Moment.load();
/**
* @summary gets date difference
* @param {Date} startDate
* @param {Date} endDate
* @returns {string}
*/
function getDuration(startDate, endDate) {
const start = moment(startDate);
const end = moment(endDate);
const units = ['years', 'months', 'days'];
const lastIndex = units.length - 1;
const parts = units
.map((unit,i) => {
const diff = Math.floor(end.diff(start, unit, true));
if (diff > 0 || i === lastIndex) {
end.subtract(unit, diff);
return `${diff} ${unit}`;
}
})
.filter(Boolean);
return parts.join(', ');
}
function Filter2() { // Calculate the Time
const spread = SpreadsheetApp.getActiveSpreadsheet();
const sheets = spread.getSheets();
const [ sheet_1, sheet_2 ] = sheets;
const row = sheet_1.getRange("A:M");
const arr_col = sheet_1.getRange("I3:I50");
const lastSeen_col = sheet_1.getRange("J3:J50");
const startDate = arr_col.getValue();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var headerRowNumber = 2;
var rows = sheet.getDataRange().offset(headerRowNumber, 0, sheet.getLastRow() - headerRowNumber).getValues();
var filter = rows.filter(row => row[9] !== '');
// var digest = filter[0][9];
for(var i=0;i<filter.length; i++){
var res = getDuration(startDate, lastSeen_col);
Logger.log(res);
}
}
答案 0 :(得分:2)
为什么要在1969年12月31日
1969年12月31日,格林尼治标准时间7时区偏移量是1970年1月1日世界标准时间(UTC),即unix epoch。因此,这很可能是由于传递给Moment
类实例的无效日期格式引起的。
问题
getRange()
方法调用返回一个Range
的实例,您必须先通过getValue()
/ getValues()
从中提取值,然后才能使用它。考虑到这一点,让我们跟踪脚本中发生的事情:
var ArrRow = sheet_1.getRange("I3:I")
返回Range
的实例mydata1
是在全局某处定义的(假设它包含一个Date
的实例)getDuration
被这样称呼:getDuration( <Range>, <Date> )
startDate
和endDate
分别是Range
和Date
的实例start
和end
包含调用moment
对象周围creates a wrapper的Date
工厂的结果。根据Moment库文档,第5步很可能是罪魁祸首,moment()
可以接受String
,Number
,Date
实例以及格式选项,但是start
改为接收Range
实例。
可能的解决方案
首先,您需要确保传递正确的类型(这就是为什么很多人更喜欢TypeScript的原因-如果那不是您的功课,至少要开始使用JSDoc-这将为您节省大量调试时间时间)。
我不知道I3:I
的范围有多大,因此我从上下文中假设它是一个包含开始日期的单元格。另请注意,由于您从格式为var sld = new Date(dateString)
的{{1}}返回了人类可读的字符串,而不是getDuration()
构造函数可以接受的Y years, M months, D days
,因此我删除了dateString
分配
此外,我建议将Date
更改为forEach()
的方法,以使代码更简洁,副作用更少。一般的经验法则是,如果输入和输出的类型相同,则可能要使用映射功能。
map()
注释
参考
function myFunction() {
Filter2();
}
function Filter2() {
const spread = SpreadsheetApp.getActiveSpreadsheet();
const sheets = spread.getSheets();
const [ sheet_1, sheet_2 ] = sheets;
const arr_col = sheet_1.getRange("I3:I");
const startDate = arr_col.getValue();
var dateString = getDuration(startDate, mydata1);
Logger.log(dateString);
}
var moment = Moment.load();
/**
* @summary gets date difference
* @param {Date} startDate
* @param {Date} endDate
* @returns {string}
*/
function getDuration(startDate, endDate) {
const start = moment(startDate);
const end = moment(endDate);
const units = ['years', 'months', 'days'];
const lastIndex = units.length - 1;
const parts = units
.map((unit,i) => {
const diff = Math.floor(end.diff(start, unit, true));
if (diff > 5 || i === lastIndex) {
end.subtract(unit, diff);
return `${diff} ${unit}`;
}
})
.filter(Boolean);
return parts.join(', ');
}
构造函数docs Date
类docs Range
方法docs getValue()
方法docs