生成完整的日期对象数组

时间:2016-02-01 23:04:41

标签: javascript date nvd3.js

问题

我使用nvd3呈现某些特定日期的数据。但是,如果没有特定日期的数据,则不存在任何记录,并且nvd3不会呈现该数据点,而是在存在的数据点之间进行插值。因此,我需要生成缺少的日期,以便nvd3显示没有与之关联的数据的日期。

我想做什么

我需要生成一个如下所示的数组:

[ {year: 2015, month: 1, day: 1},
  {year: 2015, month: 1, day: 2},
  ...
]

生成此数组的函数将采用开始日期和结束日期,并生成这两个日期之间的所有日期。

然后我将它与我的数据数组合并。这样,数据的日期将包含数据,没有数据的日期仍将显示在图表上,而不会跳过任何缺失的日期。

使用Date对象有一种简单的方法吗?即在生成这个阵列的时候,我需要知道哪个月有30天或31天,2月是特殊的,闰年等等...我可以通过指定每个月的天数来强制它,但我&#39 ; d想知道是否有更简单的方法来做到这一点。

6 个答案:

答案 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()
    };
}

Code example

答案 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循环的数组,直到结束日期为止。每个循环增加一天。