问题
我使用nvd3
呈现某些特定日期的数据。但是,如果没有特定日期的数据,则不存在任何记录,并且nvd3不会呈现该数据点,而是在存在的数据点之间进行插值。因此,我需要生成缺少的日期,以便nvd3显示没有与之关联的数据的日期。
我想做什么
我需要生成一个如下所示的数组:
[ {year: 2015, month: 1, day: 1},
{year: 2015, month: 1, day: 2},
...
]
生成此数组的函数将采用开始日期和结束日期,并生成这两个日期之间的所有日期。
然后我将它与我的数据数组合并。这样,数据的日期将包含数据,没有数据的日期仍将显示在图表上,而不会跳过任何缺失的日期。
使用Date
对象有一种简单的方法吗?即在生成这个阵列的时候,我需要知道哪个月有30天或31天,2月是特殊的,闰年等等...我可以通过指定每个月的天数来强制它,但我&#39 ; d想知道是否有更简单的方法来做到这一点。
答案 0 :(得分:3)
试试这个:
function getDateArray(startDate, days){
return Array(days)
.fill()
.map(function(e,idx) {
var d = new Date(startDate);
d.setDate(d.getDate() + idx);
return {
year: d.getFullYear(),
month: d.getMonth() + 1,
day: d.getDate() };
}
);
}
答案 1 :(得分:2)
您不一定需要知道特定月份的天数。
var date = new Date(2016, 0, 31);
console.log(date); // Sun Jan 31 2016 00:00:00 GMT-0600 (Central Standard Time)
date.setDate(date.getDate() + 1);
console.log(date); // Mon Feb 01 2016 00:00:00 GMT-0600 (Central Standard Time)
您可以迭代Date
,直到您想要到达终点。
请参阅此问题:Incrementing a date in JavaScript
修改强>
我感觉不好,我没有包含一个实现,所以这是我的方式,它与Malk's answer略有相似,除了它使用String.repeat()
而不是使得jslint不抱怨的Array构造函数返回Date
对象而不是Object文字。 String.repeat()
isn't supported by IE either。
/*jslint node:true*/
"use strict";
/*
* Function to fill a series of dates
* @param {Date} start The staring date
* @param {Number} n The number of days to fill out
* @returns {Date[]} The Date objects of the series
*/
function fillDateSeries(start, n) {
return "#".repeat(n).split("").map(function (e, i) {
var date = new Date();
date.setDate(start.getDate() + i);
return date;
});
}
// Usage
console.log(fillDateSeries(new Date(), 5));
打印:
[ Mon Feb 01 2016 18:24:29 GMT-0600 (Central Standard Time),
Tue Feb 02 2016 18:24:29 GMT-0600 (Central Standard Time),
Wed Feb 03 2016 18:24:29 GMT-0600 (Central Standard Time),
Thu Feb 04 2016 18:24:29 GMT-0600 (Central Standard Time),
Fri Feb 05 2016 18:24:29 GMT-0600 (Central Standard Time) ]
答案 2 :(得分:2)
作为替代方案,您可以完全使用数字和字符串来完成此操作,不需要Date对象。它应该更有效率,但当然只有测试才能证明。
// Start is a date string in y-m-d format
function genDates(start, count) {
var dates = [];
var d = start.split('-').map(Number);
var monthLength = [,31,28,31,30,31,30,31,31,30,31,30,31];
// Return true if year is a leap year
function isLeap(year) {return !(year % 4) && !!(year % 100) || !(year % 400)}
// Add one day to date array [year,month,day]
function addDay(d){
++d[2];
// Deal with possible leap year first
if (isLeap(d[0]) && d[1] == 2 && d[2] <= 29) return d;
// If day is too big, increment month and reset day
if (d[2] > monthLength[d[1]]) {
d[2] = 1;
++d[1];
}
// If month is too big, increment year and reset month
if (d[1] > 12) {
d[1] = 1;
++d[0];
}
return d;
}
while (count--) {
dates.push({year:d[0], month:d[1], day:d[2]});
addDay(d);
}
return dates;
}
document.write(JSON.stringify(genDates('2000-02-27', 5)));
答案 3 :(得分:1)
自己创建范围数组并不是很难迭代日期。
您可以轻松使用date.setDate(date.getDate() +1)
,如零298所示。
我创建了一个简单的例子,我认为这是一个非常直接的解决方案。
function date_range(from, to) {
if (to instanceof Date === false)
to = new Date();
if (from instanceof Date === false || from > to)
from = to;
var results = [];
while (from.getTime() !== to.getTime()) {
results.push(date_to_object(from));
from.setDate(from.getDate() +1);
}
results.push(date_to_object(to));
return results;
}
function date_to_object(date) {
return {
year: date.getFullYear(),
month: date.getMonth() +1,
day: date.getDate()
};
}
答案 4 :(得分:0)
您可以尝试这样的事情:
function dateIntervalFormatter(fromDate, toDate){
var formatedInterval = [];
while(fromDate<=toDate){
formatedInterval.push({
year: fromDate.getFullYear(),
month: fromDate.getMonth(),
day: fromDate.getDate()
});
fromDate.setDate(fromDate.getDate()+1);
};
return formatedInterval;
}
答案 5 :(得分:-1)
您可以使用模板尝试这样的事情。
将其推送到带有for循环的数组,直到结束日期为止。每个循环增加一天。