Javascript数组提供两个日期范围之间的所有日期/月份

时间:2016-05-24 09:36:23

标签: javascript date google-sheets

我正在尝试创建一个接受三个输入变量(开始日期,结束日期,粒度)的函数,并输出一个包含所有日期的数组。根据输入,输出将是每日或每月粒度。例如,如果我看2015年1月 - 2015年2月:

  • 每月将[2015-01,2015-02]
  • 每日[2015-01-01,2015-01-02,2015-01-03,...,2015-02-27,2015-02-28]

我根据其他一些帖子编写了一些内容,从逻辑上讲它似乎对我有用,但出于某种原因,每天查看每日粒度会返回31天。下面的脚本只关注每日粒度(每月会更容易) - 有人可以看看我做错了什么,如果有更有效的方法来做到这一点?

日期的输入格式为“yyyy-mm”

我意识到这可能是一个新手的错误,但至少我会学到:)

由于

function dateRange2 (startDate,endDate,granularity) {

    var dates = [];
    var d0 = startDate.split('-');
    var d1 = endDate.split('-');
    var months31 = [1,3,5,7,8,10,12];
    var months30 = [4,6,9,11];


    for (var y = d0[0]; y <= d1[0]; y++) {
        for (var m = d0[1]; m <= d1[1]; m++) {
            if (m in months31) { 
                for (var d =1;d <=31; d++) {
                    dates.push(y+"-"+m+"-"+d);
                }
            }  ///// Issue seems to be here - not switching over to next clause
            else if (m in months30) {
                for (var d =1; d <=30; d++) {
                    dates.push(y+"-"+m+"-"+d);
                }
            } else if (m=2 && y=2016) {   
                for (var d =1; d <=29; d++) {
                    dates.push(y+"-"+m+"-"+d);
                }
            } else if (m=2 && y!=2016) {   
                for (var d =1; d <=28; d++) {
                    dates.push(y+"-"+m+"-"+d);
                }
            }        
        }
    }
    return dates;
}

3 个答案:

答案 0 :(得分:2)

而不是在运算符中,使用indexOf如下:

if (months31.indexOf(m) >= 0){
}
else if (months30.index(m) >= 0){
}
运算符中的

将返回给定值是否为object的属性: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in

答案 1 :(得分:1)

其他人已经展示了如何修复代码。回答&#34;更有效率&#34;因为你还没有提供标准,所以很难。但是,如果您需要关注度分离的健壮代码,请考虑使用单独的函数来解析日期字符串,格式化日期并计算范围。

如果您有许多不同的格式可供使用,有许多用于解析和格式化日期的小型库,但如果没有,那么以下简单的函数应该适合。

如果文档和评论足够,请询问,我会提供更新。

&#13;
&#13;
/* Parse date string in ISO 8601 format as local
** @param {string} s - Date string like 2016-04-01
** @returns {Date} If date is invalid, returns an invalid Date
*/
function parseISODate(s) {
  var b = s.split(/\D/);
  var d = new Date(b[0], b[1]? b[1] - 1 : 0, b[2] || 1);
  return d && d.getMonth() == b[1] - 1? d : new Date(NaN);
}

/* Return an ISO 8601 formatted date string based on local time
** Only works for positive years (i.e. doesn't do -ve year)
** @param {Date} date - date object to create date string from
** @returns {string} dates string in yyyy-mm-dd format or default from
**                   Date.prototype.toString (i.e. "Invalid Date")
*/
function toISODate(date) {
  return date.getDate()? ('000' + date.getFullYear()).slice(-4) + '-' +
                         ('0' + (date.getMonth() + 1)).slice(-2) + '-' +
                         ('0' + date.getDate()).slice(-2) : date.toString();
}

/* Generate an array of ISO 8601 formatted date strings for a
** range of dates inclusive of start and end. Either monthly
** or daily intervals (default is daily).
** @param {string} fromDate - start date in ISO 8601 format
** @param {string} toDate   - end date in ISO 8601 format
** @param {boolean} monthly - return monthly intervals 
** @returns {Array} of date strings. If either fromDate or
**                  toDate are invalid, returns undefined.
*/
function genDatesInRange(fromDate, toDate, monthly) {
  var s = parseISODate(fromDate);
  var e = parseISODate(toDate);
  var dates = [];

  // Check that dates are valid
  if (!s.getDate() || !e.getDate()) return;

  // If monthly, set start to 1st of start month and e to 1st of end month
  if (monthly) {
    s.setDate(1);
    e.setDate(1);
  }

  while (s <= e) {
    dates.push(monthly? toISODate(s).substr(0,7) : toISODate(s));
    if (monthly) {
      s.setMonth(s.getMonth() + 1);
    } else {
      s.setDate(s.getDate() + 1);
    }
  }
  return dates;
}

// Daily
console.log(genDatesInRange('2015-05-23','2015-06-03'));       // Daily
console.log(genDatesInRange('2015-09-03','2016-03-13', true)); // Monthly
&#13;
&#13;
&#13;

答案 2 :(得分:0)

经过一些试验和错误后计算出来 - 它可能不是最漂亮的代码,但是它完成了这项工作......理想情况下,我已将每条注释行添加为单独函数的一部分。

我还注意到每个案例都使用四个&#34; if&#34;参数不需要&#34;否则如果&#34;。

function dateRangetest (start_month,start_year,end_month,end_year,granularity) {

var dates = [];
var d0 = [start_year,start_month];
var d1 = [end_year,end_month];

// var d0 = [2014,6]      FOR TESTING
// var d1 = [2016,4]

  switch (granularity) {
    case "Daily":
      for (var y = d0[0]; y <= d1[0]; y++) {
        if ((y == d0[0]) && (d0[0] != d1[0])) {     // if year=start_year && year != end year   ...  start from start_month and loop up to month 12
          for (var m = d0[1]; m <= 12; m++) {      
            for (var d =1;d <= monthday(m,y); d++) {
              dates.push(y+"-"+m+"-"+d)
            }
          } 
        }
        if ((y != d0[0]) && (y!= d1[0])) {         //  if year != start_year && year != end year ....  start from month 1 to month 12    - this would 2015 data in pulling Dec 2014 - April 2016
          for (var m = 1; m <= 12; m++) {      
            for (var d =1;d <= monthday(m,y); d++) {
              dates.push(y+"-"+m+"-"+d)
            }
          } 
        }
        if ((y != d0[0]) && (y == d1[0])) {       //   if year !=start_year && year = end_year   ....  start from month 1 up until end_month
          for (var m = 1; m <= d1[1]; m++) {      
            for (var d =1;d <= monthday(m,y); d++) {
              dates.push(y+"-"+m+"-"+d)
            }
          } 
        }

        if ((y == d0[0]) && (y == d1[0])) {      /// if year=start_year && year = end_year   ....  start from start_month to end_month
          for (var m = d0[1]; m <= d1[1]; m++) {      
            for (var d =1;d <= monthday(m,y); d++) {
              dates.push(y+"-"+m+"-"+d)
            }
          } 
        }
      }
      break;
    case "Monthly":
      for (var y = d0[0]; y <= d1[0]; y++) {
        if ((y == d0[0]) && (d0[0] != d1[0])) {     // if year=start_year && year != end year   ...  start from start_month and loop up to month 12
          for (var m = d0[1]; m <= 12; m++) {
            dates.push(y+"-"+m)
          }
        }
        if ((y != d0[0]) && (y!= d1[0])) {         //  if year != start_year && year != end year ....  start from month 1 to month 12    - this would 2015 data in pulling Dec 2014 - April 2016
          for (var m = 1; m <= 12; m++) {
            dates.push(y+"-"+m)
          }
        }
        if ((y != d0[0]) && (y == d1[0])) {       //   if year !=start_year && year = end_year   ....  start from month 1 up until end_month
          for (var m = 1; m <= d1[1]; m++) {
            dates.push(y+"-"+m)
          }
        }

        if ((y == d0[0]) && (y == d1[0])) {      /// if year=start_year && year = end_year   ....  start from start_month to end_month
          for (var m = d0[1]; m <= d1[1]; m++) {
            dates.push(y+"-"+m)
          }
        }
      }  
  }
  return dates
}

///  Function for Day Date Range
function monthday (month,year) {
var months31 = [1,3,5,7,8,10,12]
var months30 = [4,6,9,11]
var leapyear = [2016,2020,2024,2028,2032]

if (months31.indexOf(month) >=0){
  var result = 31}
  else if (months30.indexOf(month) >=0){
    var result = 30}
  else if (month==2 && leapyear.indexOf(year) >=0){
    var result = 29}
  else if (month==2 && year != 2016){
    var result = 28}

  return result
}