score:1

This one work for me in the codepen

var svg = d3.select('#chart')
               .append("svg:svg")
               .attr("height", 100)
               .attr("width", 800);

svg.append('g')
   .attr('transform', 'translate(20,20)')
   .attr('class', 'main axis date');

svg.append('g')
              .attr('transform', 'translate(20,20)')
              .attr('class', 'main axis month')
              .selectAll('text')
                .style("text-anchor", "start")
                .attr('dx', 5)
                .attr('dy', 12);

var x = d3.scaleUtc()
            .range([0,760])
            .domain([new Date(2016, 7, 20),new Date(2016, 9, 2)])
            .clamp(true);

var x1DateAxis = d3.axisBottom(x)
               .ticks(d3.utcDay, 1)
               .tickFormat(d3.timeFormat('%d'))
               .tickSize(16, 0, 0);

var x1MonthAxis = d3.axisBottom(x)
              .ticks(d3.utcMonth, 1)
              .tickFormat(d3.timeFormat('%B'))
              .tickSize(24, 0, 0);

svg.select('.axis.month')
          .call(x1MonthAxis)
          .selectAll('text')
            .style('text-anchor', 'start');

svg.select('.axis.date')
          .call(x1DateAxis)
          .selectAll('text')
            .style('text-anchor', 'start')
            .attr('dy', -6)
            .attr('dx', +3);

score:1

Your assumption is not correct. In D3, the scaleUTC() (which is equivalent to scaleTime() operating in Coordinated Universal Time) scale does display the month tick at the beginning of the month, not at its end.

This is probably the cause of your mistake: despite the fact that in d3.format the months start at 01...

month as a decimal number [01,12].

... which makes January being 01 and December being 12, in plain JavaScript, new Date() sets the months from 0 to 11. That is, January is 0 and December is 11.

We can easily see that this is the case in this following snippet, where I copied your code exactly as it is, changing only the start and end dates:

.domain([new Date(2016, 0, 20),new Date(2016, 2, 2)])
//January here ---------^      March here-----^

You can see that the scale starts at 20th January and ends at 2nd March. Look at the result, both "February" and "March" labels are exactly at the beginning of the respective months:

var svg = d3.select('#chart')
               .append("svg:svg")
               .attr("height", 100)
               .attr("width", 800);

svg.append('g')
   .attr('transform', 'translate(20,20)')
   .attr('class', 'main axis date');

svg.append('g')
              .attr('transform', 'translate(20,20)')
              .attr('class', 'main axis month')
              .selectAll('text')
                .style("text-anchor", "start")
                .attr('dx', 5)
                .attr('dy', 12);

var x = d3.scaleUtc()
            .range([0,760])
            .domain([new Date(2016, 0, 20),new Date(2016, 2, 2)])
            .clamp(true);

var x1DateAxis = d3.axisBottom(x)
               .ticks(d3.utcDay, 1)
               .tickFormat(d3.timeFormat('%d'))                        .tickSize(16, 0, 0);

var x1MonthAxis = d3.axisBottom(x)
              .ticks(d3.utcMonth, 1)
              .tickFormat(d3.timeFormat('%B'))
              .tickSize(24, 0, 0);

svg.select('.axis.month')
          .call(x1MonthAxis)
          .selectAll('text')
            .style('text-anchor', 'end');

svg.select('.axis.date')
          .call(x1DateAxis)
          .selectAll('text')
            .style('text-anchor', 'end')
            .attr('dy', -6)
            .attr('dx', -1);
#chart {
  width: 800px;
  height: 100px;
  margin: 0 auto;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<div id="chart"></div>


Related Query