[英]JavaScript: get all months between two dates?
我有两个这样的日期字符串:
var startDate = '2012-04-01';
var endDate = '2014-11-01';
我想得到一个这样的字符串数组:
var dates = ['2012-04-01', '2012-05-01', '2012-06-01' .... '2014-11-01',];
到目前为止,这就是我所拥有的,但它非常难看:
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);
有没有更好的办法? JSF中。
这应该产生所需的输出:
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;
}
只需使用您现有的日期格式调用它:
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"]
您还可以使用出色的 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');
}
如果加载额外的库不是问题,您可以随时尝试很棒的 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在这里
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 monthNum = year === fromYear ? fromMonth : 0; const monthLimit = year === toYear ? toMonth : 11; for(; monthNum <= monthLimit; monthNum++) { let month = monthNum + 1; 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');
您正在处理“逻辑”跳跃,因此您实际上并不需要计时算法。 所以这是一个简单的计数问题:
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);
这是一个仅对特定 YYYY-MM-DD 格式使用字符串操作的解决方案:
function monthsBetween(...args) { let [a, b] = args.map(arg => arg.split("-").slice(0, 2) .reduce((y, m) => m - 1 + y * 12)); return Array.from({length: b - a + 1}, _ => a++) .map(m => ~~(m / 12) + "-" + ("0" + (m % 12 + 1)).slice(-2) + "-01"); } console.log(monthsBetween('2012-04-01', '2014-11-01'));
使用 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;
};
上述所有解决方案都以 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');
可能会共享一个更简单的代码
这是另一个解决方案,使用 Date 对象:
const enumerateMonths = (from, to) => {
const current = new Date(from)
current.setUTCDate(1)
current.setUTCHours(0, 0, 0, 0)
const toDate = new Date(to)
const months = []
while (current.getTime() <= toDate.getTime()) {
months.push(current.getUTCFullYear() + "-" + `${current.getUTCMonth() + 1}`.padStart(2, "0"))
current.setUTCMonth(current.getUTCMonth() + 1)
}
return months
}
此解决方案假定您提供 Date 对象或 ISO 8601 字符串。 请注意,ISO 8601 日期不一定必须包含小时-分钟-秒部分。 "2012-01-14"
是有效的 ISO 8601 日期。
仍然不是一个非常优雅的答案,但可以得到你想要的字符串数组:
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 链接在这里:http: //jsfiddle.net/8kut035a/
这是我的解决方案,借助数学和 O(n)
determineMonthInInterval(startDate, endDate) {
let startYear = startDate.getFullYear();
let endYear = endDate.getFullYear();
let startMonth = startDate.getMonth() + 1;
let endMonth = endDate.getMonth() + 1;
let monthAmount = (endMonth - startMonth) + 1 + (12 * (endYear - startYear));
let dates = [];
let currMonth = startMonth;
let currYear = startYear;
for( let i=0; i<monthAmount; i++){
let date = new Date(currYear + "/"+currMonth+"/1");
dates.push(date);
currYear = startYear + Math.floor((startMonth+i) / 12);
currMonth = (currMonth) % 12 +1;
}
return dates;
}
这是另一种选择:
getRangeOfMonths(startDate: Date, endDate: Date) {
const dates = new Array<string>();
const dateCounter = new Date(startDate);
// avoids edge case where last month is skipped
dateCounter.setDate(1);
while (dateCounter < endDate) {
dates.push(`${dateCounter.getFullYear()}-${dateCounter.getMonth() + 1}`);
dateCounter.setMonth(dateCounter.getMonth() + 1);
}
return dates;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.