igorgetmeabrain
igorgetmeabrain

Reputation: 15

d3.js y-axis not displaying months correctly

I'm simply trying to create a y-axis labelled from January to December, but I can't understand why my code creates: January, March, March, April.... December. Can anyone explain this to me please? Thanks!

const w = 1078;
const h = 666;
const padding = 70;

const svg = d3
  .select("#svg-container")
  .append("svg")
  .attr("width", w)
  .attr("height", h);

const months = Array(12)
  .fill(0)
  .map((v, i) => new Date().setMonth(i));

const yScale = d3
  .scaleTime()
  .domain([months[11], months[0]])
  .range([h - padding, padding]);

const yAxis = d3
  .axisLeft(yScale)
  .tickValues(months)
  .tickFormat(d3.timeFormat("%B"));

svg
  .append("g")
  .attr("transform", "translate(" + padding + ", -20)")
  .attr("id", "y-axis")
  .call(yAxis);
body {
  background: gray;
}

svg {
  background: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="svg-container"></div>

Upvotes: 1

Views: 118

Answers (1)

adelriosantiago
adelriosantiago

Reputation: 8134

That happens because setMonth() also sets the day you are currently in. Today is day 30 and February 2021 has only 28 days, therefore the non-existing February 30 2021 is in fact March 2 2021. You can see this if you print the dates in a different format:

enter image description here

To fix this, you can use the full Date function new Date(2021, i, 1)

const w = 1078;
const h = 666;
const padding = 70;

const svg = d3
  .select("#svg-container")
  .append("svg")
  .attr("width", w)
  .attr("height", h);

const months = Array(12)
  .fill(0)
  .map((v, i) => new Date(2021, i, 1));

const yScale = d3
  .scaleTime()
  .domain([months[11], months[0]])
  .range([h - padding, padding]);

const yAxis = d3
  .axisLeft(yScale)
  .tickValues(months)
  .tickFormat(d3.timeFormat("%B %d"));

svg
  .append("g")
  .attr("transform", "translate(" + padding + ", -20)")
  .attr("id", "y-axis")
  .call(yAxis);
body {
  background: gray;
}

svg {
  background: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="svg-container"></div>

Good for you for posting this on the 30th, otherwise there would be a hidden bug waiting to appear!

Additional resources

MBostock's month axis example: https://bl.ocks.org/mbostock/1849162

D3 Scaletime documentation: https://observablehq.com/@d3/d3-scaletime

Upvotes: 1

Related Questions