如何计算两个日期之间的差额

时间:2020-04-30 22:00:33

标签: javascript google-apps-script google-sheets momentjs

我要做的就是这个。

比方说,在Google表格中,我有一个页面,其中包含以下列:

在I3列中,我的日期为11/30/19。 在J3栏中,我的今天是4/30/20。 我希望能够计算出这两个日期之间的差额,并告诉我自19/30/19以来已经有多少个月了。

enter image description here

当前,我认为代码可以正常工作,但是我得到的结果是:

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

1 个答案:

答案 0 :(得分:2)

为什么要在1969年12月31日

1969年12月31日,格林尼治标准时间7时区偏移量是1970年1月1日世界标准时间(UTC),即unix epoch。因此,这很可能是由于传递给Moment类实例的无效日期格式引起的。

问题

getRange()方法调用返回一个Range的实例,您必须先通过getValue() / getValues()从中提取值,然后才能使用它。考虑到这一点,让我们跟踪脚本中发生的事情:

  1. var ArrRow = sheet_1.getRange("I3:I")返回Range的实例
  2. mydata1是在全局某处定义的(假设它包含一个Date的实例)
  3. 因此,
  4. getDuration被这样称呼:getDuration( <Range>, <Date> )
  5. startDateendDate分别是RangeDate的实例
  6. startend包含调用moment对象周围creates a wrapperDate工厂的结果。

根据Moment库文档,第5步很可能是罪魁祸首,moment()可以接受StringNumberDate实例以及格式选项,但是start改为接收Range实例。

可能的解决方案

首先,您需要确保传递正确的类型(这就是为什么很多人更喜欢TypeScript的原因-如果那不是您的功课,至少要开始使用JSDoc-这将为您节省大量调试时间时间)。

我不知道I3:I的范围有多大,因此我从上下文中假设它是一个包含开始日期的单元格。另请注意,由于您从格式为var sld = new Date(dateString)的{​​{1}}返回了人类可读的字符串,而不是getDuration()构造函数可以接受的Y years, M months, D days,因此我删除了dateString分配

此外,我建议将Date更改为forEach()的方法,以使代码更简洁,副作用更少。一般的经验法则是,如果输入和输出的类型相同,则可能要使用映射功能。

map()

注释

  1. 答案假设您使用的是V8引擎(如果您不使用-switch to it,则将来会淘汰旧版本的引擎,此外,您还可以使用所有最丰富的语言功能,这是一个奖励)大多数])。

参考

    MDN上的
  1. 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
  2. Datedocs
  3. Range方法docs
  4. getValue()方法docs