解析日期时浏览器挂起

时间:2017-10-28 04:18:30

标签: javascript datetime d3.js

当我使用虚拟数据作为日期时,即当我仅使用年数时,我成功地使这种可视化(小倍数的堆积区域图表)工作,形式略有不同。但是,当我使用这样的实际日期时,它会出现问题:

Record,Code,2008-1-1,2008-2-1,2008-3-1,2008-4-1,2008-5-1,2008-6-1,2008-7-1...

代替这个虚拟数据,工作正常

Record,Code,1895,1896,1897,1898,1899,1900,1901...

当我使用完整日期时,浏览器会挂起;没有错误消息。我以前修复了解析错误,但这个似乎超出了我的能力范围。

这是非工作的Plunker:https://plnkr.co/edit/fOlpxo648OyCSM7Sq8ak?p=preview 另一个Plunker,一个实际加载,但使用虚拟数据,在这个问题的底部。

这段代码似乎特别成问题:

function createDatesArr(start, end) {
var arr = [];
for (var i = start; i <= end; i++ ) {
    arr.push((i));  //      arr.push(String(i));
}
return arr;
}

稍微不同的形式,我会收到一条错误消息,&#34; date&#34;尚未定义。我已尝试使用以下代码解决此问题:

var dateFormat = d3.time.format("%Y-%m-%d");
var startDate = new Date('2008-1-1');
var endDate = new Date ('2017-12-1');
var dates = createDatesArr(startDate, endDate); 

或者像这样:

var dateFormat = d3.time.format("%Y-%m-%d");
var startYear = "2008-1-1";
var endYear = "2017-12-1";
var dates = createYearsArr(startYear, endYear);

或者像这样:

var dateFormat = d3.time.format("%Y-%m-%d");
var startDate = d3.min(dataset, function(d) { return d.Date; });
var endDate = d3.max(dataset, function(d) { return d.Date; });
var dates = createDatesArr(startDate, endDate);

或者,通过定义&#34;日期&#34;像这样:

d3.csv(dataPath, function(data) {
    var dates = d3.keys(data[0]).slice(1);
    data = data.filter(function(d) {
            return true;
    });
    var dates = d3.keys(data[0]).slice(1);

这些都没有奏效,但我希望有人可以帮我解决这个问题。

这是另一个真正有用的Plunker,它展示了我最终想要实现的目标,尽管使用虚拟数据(仅限年份)来表示日期:http://plnkr.co/edit/jRC8iQg2kdtlZWtGE020?p=preview

请帮忙。

3 个答案:

答案 0 :(得分:4)

你是对的,你在这段代码中的问题

function createDatesArr(start, end) {
  var arr = [];
  for (var i = start; i <= end; i++ ) {
    arr.push((i));  //      arr.push(String(i));
  }
  return arr;
}

更准确地说 - i++;

请看下面的图片,变量i它是一个以毫秒为单位的日期。在每次循环迭代后,将它增加一毫秒。但是,我可以看到你的数据点之间是一个月。

Record,Code,2008-1-1,2008-2-1,2008-3-1,2008-4-1,2008-5-1,2008-6-1,2008-7-1...

enter image description here

所以你应该在每次循环迭代后增加i一个月来解决你的问题。

您可以使用d3.time.month.offset

执行此操作
for (var i = start; i <= end; i = d3.time.month.offset(i, 1)) {
  arr.push((i));
}

之后,你应该删除dateFormat(...)因为数据项是完全有效的javascript日期并稍微重写transformData函数,看看我的fork of you plnkr(看起来不正确应用颜色,我认为你可以解决它,但除此之外它有效。)

答案 1 :(得分:2)

首先在这个片段中:

function createDatesArr(start, end) {
 var arr = [];
  for (var i = start; i <= end; i++ ) {
    arr.push((i));  //      arr.push(String(i));
  }
  return arr;
}

使用i ++将无法正常工作,因为您尝试在有效表达式上使用后缀操作。你不能用这个来跳过这几天:

( Fri Dec 01 2017 00:00:00 GMT+0400 (+04) ) ++

如果你想在整个过程中得到所有月份,你可以使用下面这个简单的片段:

   function createDatesArr(startDate, endDate) {
       var _start = new Date(startDate),
           _end = new Date(endDate),
           _result = [];

       while(_start < _end){
           _result.push(_start);
           // going next
           var _newDate = _start.setDate(_start.getDate() + 1);
               _start = new Date(_newDate);
       }
       return _result;
    }

答案 2 :(得分:2)

只是为了提供这个问题的其他信息,已经有两个好的答案:你不需要那个可怕的createDatesArr函数(这是你问题的原因)。

您可以使用time.ticks([interval])轻松获取时间刻度的开始日期和结束日期之间的日期数组,其中包含:

  

从比例的域中返回代表日期。返回的刻度值均匀分布(大部分),具有合理的值(例如每天午夜),并且保证在域的范围内。

不仅比你的功能更安全,而且它也是惯用 D3,这意味着其目的很容易被其他D3程序员理解。

以下是使用v3的演示,这是您的版本。我将结束日期更改为2009而不是2017,因此我们在控制台中的日期会更少。检查一下:

var startDate = new Date('2008-1-1');
var endDate = new Date('2009-6-1');
var dates = d3.time.scale()
  .domain([startDate, endDate])
  .ticks(d3.time.months, 1);

console.log(dates)
<script src="https://d3js.org/d3.v3.min.js"></script>

实际上,这可能更短,只需一行,缩短时间范围,只使用d3.time.monthsd3.time.month.range

var dates = d3.time.month.range(new Date('2008-1-1'), new Date('2009-6-1'), 1)

console.log(dates)
<script src="https://d3js.org/d3.v3.min.js"></script>