How do I display dates on the x-axis for nvd3 / d3.js?
Asked Answered
H

2

52

I'm using nvd3, but I think this is a general d3.js question about time scale and formatting. I've created a simple example that illustrates the problem (see code below):

If I omit .tickFormat for the xAxis, it works fine without date formatting. With the example below I get the error:

Uncaught TypeError: Object 1326000000000 has no method 'getMonth'

nv.addGraph(function() {

    var chart = nv.models.lineChart();

    chart.xAxis
         .axisLabel('Date')
         .rotateLabels(-45)
         .tickFormat(d3.time.format('%b %d')) ;

     chart.yAxis
         .axisLabel('Activity')
         .tickFormat(d3.format('d'));

     d3.select('#chart svg')
         .datum(fakeActivityByDate())
       .transition().duration(500)
         .call(chart);

     nv.utils.windowResize(function() { d3.select('#chart svg').call(chart) });

     return chart;
});

function days(num) {
    return num*60*60*1000*24
}

/**************************************
 * Simple test data generator
 */

function fakeActivityByDate() {
    var lineData = [];
    var y = 0;
    var start_date = new Date() - days(365); // One year ago

    for (var i = 0; i < 100; i++) {
        lineData.push({x: new Date(start_date + days(i)), y: y});
        y = y + Math.floor((Math.random()*10) - 3);
    }

    return [
        {
            values: lineData,
            key: 'Activity',
            color: '#ff7f0e'
        }
    ];
 }

The example (now fixed) is in nvd3 with date axis.

Halfprice answered 27/12, 2012 at 17:45 Comment(3)
You should create a jsFiddle for your example when asking questions like this. It makes it easier for people answering questions to see your code example working live and easily editable.Putrescible
This is a good idea. I tried making one, but the css looks like it is not applied: jsfiddle.net/ultrasaurus/x7epG/3 -- anyone know what I did wrong?Halfprice
Looks like the fiddle isn't working any longer. The libraries that it references now 404.Monophyletic
P
63

Try creating a new Date object before the tick for the x-axis gets passed to the formatter:

.tickFormat(function(d) { return d3.time.format('%b %d')(new Date(d)); })

See the documentation for d3.time.format to see how you can customize the formatting string.

Putrescible answered 27/12, 2012 at 20:11 Comment(5)
Thanks! That works, updated the example here: ultrasaurus.github.com/nvd3-simpleline/date_axis.html -- but can you explain why it works? and why are the tick marks at week intervals? (fine for my purpose, but would like to understand)Halfprice
@Halfprice Glad I could help. If I've answered your question, you should accept my answer to mark the question as answered for others to see.Putrescible
Quick comment which helped me: date objects are in milliseconds in Javascript, so I needed to ensure my chart data (being generated by a Python API) was producing x values in milliseconds (since the epoch) for JS/d3 to parse and format my x axis values properly.Despondency
If you're having an issue with the tick marks or chart grid not being lined up with whole date values, check out how to fix it here: groups.google.com/d/msg/d3-js/OGsyiNDfywo/EpmvLg5ydY4JSuperstratum
I wanted to use just integers, so I wanted to share my relatively simple addition to this: chart.tickFormat(function(d) { if (d % 1 == 0) { return(d); } })Sepulveda
S
34

Adding on to seliopou's answer, to correctly align the dates with the x-axis, try this:

chart.xAxis
      .tickFormat(function(d) {
          return d3.time.format('%d-%m-%y')(new Date(d))
      });

  chart.xScale(d3.time.scale()); //fixes misalignment of timescale with line graph
Shipment answered 15/3, 2014 at 2:8 Comment(2)
I had to use d3.time.scale.utc() as per this answerCoordinate
I had misalignment problem with timescale as well. This solution fixed my problem. Thank you very much!!!Lucialucian

© 2022 - 2024 — McMap. All rights reserved.