JavaScript:获取两个日期之间的所有月份?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30464628/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 12:13:25  来源:igfitidea点击:

JavaScript: get all months between two dates?

javascript

提问by Richard

I have two date strings like this:

我有两个这样的日期字符串:

var startDate = '2012-04-01';
var endDate = '2014-11-01';

And I want to end up with an array of strings like this:

我想以这样的字符串数组结束:

var dates = ['2012-04-01', '2012-05-01', '2012-06-01' .... '2014-11-01',];

So far this is what I've got, but it's pretty ugly:

到目前为止,这是我所拥有的,但它非常丑陋:

var startDate = '2012-04-01';
var endDate = '2014-11-01';
var start = new Date(Date.parse(startDate));
var end = new Date(Date.parse(endDate))
var dates = [];
for (var i = start.getFullYear(); i < end.getFullYear() + 1; i++) {
    dates.push(i + '-' + '-01');
}
console.log(dates);

Is there a better way? JSFiddle.

有没有更好的办法?JSFiddle

回答by McCroskey

You can also use the excellent moment.js library:

您还可以使用优秀的 moment.js 库:

var startDate = moment('2012-04-01');
var endDate = moment('2014-11-01');

var result = [];

if (endDate.isBefore(startDate)) {
    throw "End date must be greated than start date."
}      

while (startDate.isBefore(endDate)) {
    result.push(startDate.format("YYYY-MM-01"));
    startDate.add(1, 'month');
}

JSFiddle

JSFiddle

回答by Rob M.

This should produce the desired output:

这应该会产生所需的输出:

function dateRange(startDate, endDate) {
  var start      = startDate.split('-');
  var end        = endDate.split('-');
  var startYear  = parseInt(start[0]);
  var endYear    = parseInt(end[0]);
  var dates      = [];

  for(var i = startYear; i <= endYear; i++) {
    var endMonth = i != endYear ? 11 : parseInt(end[1]) - 1;
    var startMon = i === startYear ? parseInt(start[1])-1 : 0;
    for(var j = startMon; j <= endMonth; j = j > 12 ? j % 12 || 11 : j+1) {
      var month = j+1;
      var displayMonth = month < 10 ? '0'+month : month;
      dates.push([i, displayMonth, '01'].join('-'));
    }
  }
  return dates;
}

Just call it with your existing date format:

只需使用您现有的日期格式调用它:

dateRange('2013-11-01', '2014-06-01')
// ["2013-11-01", "2013-12-01", "2014-01-01", "2014-02-01", "2014-03-01", "2014-04-01", "2014-05-01", "2014-06-01", "2014-07-01", "2014-08-01", "2014-09-01", "2014-10-01", "2014-11-01", "2014-12-01"]

回答by Michiel

If loading an extra library isn't a problem, you could always try the awesome MomentJS.
Gives for very clean and powerful date manipulation.

如果加载一个额外的库不是问题,你总是可以尝试很棒的 MomentJS。
提供非常干净和强大的日期操作。

var startDate = moment('2012-04-01');
var endDate = moment('2014-11-01');

var dates = [];
endDate.subtract(1, "month"); //Substract one month to exclude endDate itself

var month = moment(startDate); //clone the startDate
while( month < endDate ) {
    month.add(1, "month");
    dates.push(month.format('YYYY-MM-DD'));
}

console.log(dates);

JSFiddle here

JSFiddle在这里

回答by Matthieu Chavigny

  const getMonths = (fromDate, toDate) => {
    const fromYear = fromDate.getFullYear();
    const fromMonth = fromDate.getMonth();
    const toYear = toDate.getFullYear();
    const toMonth = toDate.getMonth();
    const months = [];
    for(let year = fromYear; year <= toYear; year++) {
      let month = year === fromYear ? fromMonth : 0;
      const monthLimit = year === toYear ? toMonth : 11;
      for(; month <= monthLimit; month++) {
        months.push({ year, month })
      }
    }
    return months;
  }
const sample = getMonths(new Date('2022-07-28'), new Date('2023-03-20'));
console.log(sample);
document.write('check the console output');

https://jsfiddle.net/xfayoqvs/

https://jsfiddle.net/xfayoqvs/

回答by bitifet

You are handling "logical" jumps, so you doesn't actually need timing arthmetics. So this is a simple counting problem:

您正在处理“逻辑”跳转,因此您实际上并不需要计时算法。所以这是一个简单的计数问题:

var startDate = '2012-04-01';
var endDate = '2014-11-01';
var dates = [];

var d0 = startDate.split('-');
var d1 = endDate.split('-');

for (
    var y = d0[0];
    y <= d1[0];
    y++
) {
    for (
        var m = d0[1];
        m <= 12;
        m++
    ) {
        dates.push(y+"-"+m+"-1");
        if (y >= d1[0] && m >= d1[1]) break;
    };
    d0[1] = 1;
};

console.log(dates);

回答by golf4sp

All solutions above run in O(n^2) time complexity, which is not very efficient. See below solution in O(n) time complexity:

以上所有解决方案都以 O(n^2) 时间复杂度运行,这不是很有效。请参阅以下 O(n) 时间复杂度的解决方案:

function getAllMonths(start, end){ 
 let startDate = new Date(start);
 let startYear = startDate.getFullYear();
 let startMonth = startDate.getMonth()+1;
 
 let endDate = new Date(end);
 let endYear = endDate.getFullYear();
 let endMonth = endDate.getMonth()+1;
 
 let countMonth = 0;
 let countYear = 0;
 let finalResult = [];

 for(let a=startYear; a<=endYear; a++){

  if(startYear<endYear){
   if(countYear==0){
    countMonth += 12-startMonth;
            }else 
   if(countYear>0){
    countMonth += 12;
            }
   countYear+=1;
   startYear++;
        }else 
  if(startYear==endYear){
   countMonth+=endMonth;
        }
    }
 for(let i=startMonth; i<=countMonth+startMonth; i++){
  finalResult.push(startDate.getFullYear()+(Math.floor(i/12)) + "-" + Math.round(i%13) + "-" + "01");
    }
 return finalResult;
}

getAllMonths('2016-04-01', '2018-01-01');

Might share a much more simpler code

可能会分享更简单的代码

回答by RR90

An example to get all first days of months between a given date and now using moment.js.

使用moment.js获取给定日期和现在之间所有月份的第一天的示例。

   var getMonths = function (startDate) {
    var dates = [];
    for (var year = startDate.year(); year <= moment().year(); year++) {
        var endMonth = year != moment().year() ? 11 : moment().month();
        var startMonth = year === startDate.year() ? startDate.month() : 0;
        for (var currentMonth = startMonth; currentMonth <= endMonth; currentMonth = currentMonth > 12 ? currentMonth % 12 || 11 : currentMonth + 1) {
            var month = currentMonth + 1;
            var displayMonth = month < 10 ? '0' + month : month;
            dates.push([year, displayMonth, '01'].join('-'));
        }
    }
    return dates;
};

回答by Robert Cunningham

Still not a very elegant answer, but arrives at the array of strings you want:

仍然不是一个非常优雅的答案,但会得到您想要的字符串数组:

var startDate = '2012-04-01';
var endDate = '2014-11-01';
var start = new Date(startDate);
var end = new Date(endDate);
var dates = [];
for (var i = start.getFullYear(); i < end.getFullYear() + 1; i++) {
    for (var j = 1; j <= 12; j++) {
      if (i === end.getFullYear() && j === end.getMonth() + 3) {
        break;
      }
      else if (i === 2012 && j < 4){
        continue;
      }
      else if (j < 10) {
        var dateString = [i, '-', '0' + j, '-','01'].join('');
        dates.push(dateString)
        }
      else {
        var dateString = [i, '-', j, '-','01'].join('');
        dates.push(dateString);
        }
    }
}
console.log(dates);

jsfiddle link here: http://jsfiddle.net/8kut035a/

jsfiddle 链接在这里:http: //jsfiddle.net/8kut035a/