title: d3 v4 why are there duplicate ticks on the X Axis (how to work tickValues)?
body: <p>Here is my reduction:</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>var CreateChart = (function() {
      var chtChartConstrictor = document.getElementById("chtChartConstrictor");
      var myChart;
  
      var drawChart = function(options) {
          // Set dimensions and margins of the graph
          var margin = {
              top: 20,
              right: 0,
              bottom: 0,
              left: 0,
          };
          var chtChartConstrictorMetrics = chtChartConstrictor.getBoundingClientRect();
          var width = chtChartConstrictorMetrics.width;
          var height = chtChartConstrictorMetrics.height;
  
          var parseTime = d3.timeParse("%Y-%m-%d");
          var formatTime = d3.timeFormat("%Y-%m-%d");
          // format the data
          options.line1.forEach(function(d) {
              d.date = parseTime(d.date);
              d.close = +d.close;
          });
          // parse the date / time
  
          if (options.chartType === "line") {
              
              // set the ranges
              let x = d3.scaleTime().range([0, width]).domain(
                  d3.extent(options.line1, function(d) {
                      return d.date;
                  })
              );
              let y = d3.scaleLinear().range([height - margin.top - margin.bottom, 0]).domain([
                  0,
                  d3.max(options.line1, function(d) {
                      return d.close;
                  }),
              ]);
  
              // define the area
              var area = d3
                  .area()
                  .x(function(d) {
                      
                      return x(d.date);
                  })
                  .y0(height)
                  .y1(function(d) {
                      
                      return y(d.close);
                  });
              // define the line
              var valueline = d3
                  .line()
                  .x(function(d) {
                      
                      return x(d.date);
                  })
                  .y(function(d) {
                      return y(d.close);
                  });
  
              var svg = d3
                  .select("#chtChartConstrictor")
                  .append("svg")
                  .attr("width", width + margin.left + margin.right)
                  .attr("height", height + margin.top + margin.bottom)
                  .append("g")
                  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
              svg.append("path").attr("class", "cht-LineChart_Line").attr("d", valueline(options.line1));
              // add the area
              svg.append("path").data(options.line1).attr("class", "cht-LineChart_Fill").attr("d", area(options.line1));
  
              // add the X Axis
              svg.append("g").attr("class", "cht-LineChart_XAxis").attr("transform", "translate(0," + (height - 40) + ")").call(customXAxis);
              function customXAxis(g) {
                  g.call(d3.axisBottom(x).tickFormat(d3.timeFormat("%Y-%m-%d")));
                  g.select(".domain").remove();
                  g.selectAll("line").remove();
                  g.selectAll("text").attr("class", "cht-LineChart_XAxisNumber");
              }
              // add the Y Axis
              svg.append("g").attr("class", "cht-LineChart_YAxis").attr("transform", "translate(-5,0)").call(customYAxis);
              function customYAxis(g) {
                  g.call(d3.axisRight(y));
                  g.select(".domain").remove();
                  g.selectAll("line").remove();
                  g.select(".cht-LineChart_YAxis text:first-of-type").remove();
                  g.selectAll("text").attr("class", "cht-LineChart_YAxisNumber");
              }
  
              // Gridline
              var gridlines = d3.axisLeft().tickFormat("").tickSize(-width).scale(y);
  
              svg.append("g").attr("class", "cht-LineChart_GridLineContainer").call(gridlines);
              svg.selectAll(".cht-LineChart_GridLineContainer line").attr("class", "cht-LineChart_GridLine");
              // Tidy up the generation by removing the text and path as we don't use them
              svg.selectAll(".cht-LineChart_GridLineContainer text").remove();
              svg.selectAll(".cht-LineChart_GridLineContainer path").remove();
          }
      };
  
      var destroyChart = function() {};
  
      var publicAPI = {
          DrawChart: drawChart,
          DestroyChart: destroyChart,
      };
      return publicAPI;
  })();
  
  CreateChart.DrawChart({
      chartType: "line",
      line1: [
          { date: "2016-12-25", close: 43 },
          { date: "2016-12-26", close: 57 },
          { date: "2016-12-27", close: 55 },
          { date: "2016-12-28", close: 44 },
          { date: "2016-12-29", close: 45 },
          { date: "2016-12-30", close: 30 },
          { date: "2016-12-31", close: 36 },
      ],
      line2: [],
  });</code></pre>
  <pre class="snippet-code-css lang-css prettyprint-override"><code>#chtChartConstrictor {
   height: 320px;
   width: 100%;
  }
  
  .cht-LineChart_Line {
   fill: transparent;
   stroke: #f90;
     stroke-width: 2px;
  }
  
  .cht-LineChart_Fill {
   fill: rgba(73,255,255,.5);
  }
  
  .cht-LineChart_GridLine {
      stroke-dasharray: 4px 4px;
      stroke: #ddd;
  }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"&gt;&lt;/script&gt;
  &lt;div id="chtChartConstrictor"&gt;&lt;/div&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p>I cannot fathom why I am getting multiple duplicate ticks (dates) on the X Axis? Could anyone send me on the right path? I'd like to see a tick for each of the data points and nothing more.</p>