生成完整的日期对象数组

Generate a full array of date objects

本文关键字:日期 对象 数组      更新时间:2023-09-26

问题

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

我想做什么

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

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

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

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

有没有一种简单的方法可以使用Date对象执行此操作? 即在生成此数组时,我需要知道哪些月份有 30 或 31 天,二月是特殊的,闰年等,等等......我可以通过指定每个月的天数来暴力破解它,但我想知道是否有更简单的方法可以做到这一点。

试试这个:

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

您不一定需要知道特定月份的天数。

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,直到您想要到达终点。

请参阅此问题:在 JavaScript 中递增日期


编辑

我感觉很糟糕我没有包含实现,所以这是我的方式,它与 Malk 的答案略有相似,只是它使用 String.repeat() 而不是 Array 构造函数,它可以防止 jslint 抱怨并返回一个Date对象而不是对象文字。 IE 也不支持String.repeat()

/*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) ]

作为替代方案,您可以纯粹使用数字和字符串来执行此操作,不需要 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)));

遍历日期以自己创建范围数组并不难。您可以轻松使用 date.setDate(date.getDate() +1) ,正如 zero298 所建议的那样。

我创建了一个简单的例子,我认为这是一个非常简单的解决方案。

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

代码示例

你可以尝试这样的事情:

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;
}

您可以使用模板尝试这样的事情。

并将其推送到带有 for 循环的数组,直到达到结束日期。 每循环增加一天。