'Why axisBottom result wrong position if my data contain date minute?

I found that my point circle and axis bottom positions don't match if the timesamp contains minutes like "2021-11-23T15:20:54,000Z". But if I use the time without the minutes the bottom axis is in the right position for example " '2022-02-01T00:00:00.000Z'.

Bellow is incorrect. enter image description here

This one correct position. enter image description here

  const chartRef = useRef<SVGSVGElement | null>(null);

  const margin = {
    top: 5,
    right: 20,
    bottom: 20,
    left: 30,
  };

  const parseTime = timeParse('%Y-%m-%dT%H:%M:%S.%LZ');

  let values: ChartData[] = [];
  const parsedData: ParsedData[] = [];
  const obj: any = new Object();
  dataLineChart.forEach((d) => {
    values.push(d);
  });
  obj.values = values;
  parsedData.push(obj);

  const width = widthSVG - margin.left - margin.right;
  const height = heightSVG - margin.top - margin.bottom;

  const minDate = min(parsedData[0].values, (d) => parseTime(d.timestamp));
  const maxDate = max(parsedData[0].values, (d) => parseTime(d.timestamp));

  const minValue = min(parsedData[0].values, (v) => v.value);
  const maxValue = max(parsedData[0].values, (v) => v.value);

  let xScale, yScale;
  if (minDate && maxDate) {
    xScale = scaleTime().domain([minDate, maxDate]).range([0, width]);
  }
  if (minValue && maxValue) {
    yScale = scaleLinear().domain([minValue, maxValue]).range([height, 0]);
  }

  const lineGenerator = line<ChartData>()
    .x((d) => xScale(parseTime(d.timestamp)))
    .y((d) => yScale(d.value))
    .curve(curveCatmullRom.alpha(0.5));

  useEffect(() => {
    const svg = select(chartRef.current)
      .append('g')
      .attr('transform', `translate(${margin.left}, ${margin.top})`)
      .attr('fill', '#d5d5d5');

    svg.append('defs');
    svg.call(createGradient, [chartColor]);
    svg.call(createGlowFilter);

    svg
      .selectAll('line')
      .data(parsedData)
      .enter()
      .append('path')
      .attr('d', (d) => {
        const v = d.values as ChartData[];
        const lineValues = lineGenerator(v)?.slice(1);
        const splitedValues = lineValues?.split(',') as string[];
        let path: string = '';
        if (splitedValues.length > 0) {
          path = `M0,${height},${lineValues},l0,${
            height - parseInt(splitedValues[splitedValues.length - 1])
          }`;
        }
        return path;
      })
      .style('fill', `url(${chartColor})`)
      .attr('y2', `-${height}px`);

    svg
      .selectAll('line')
      .data(parsedData)
      .enter()
      .append('path')
      .attr('d', lineGenerator(parsedData[0].values))
      .attr('stroke-width', 1)
      .style('fill', 'none')
      .style('filter', 'url(#glow)')
      .attr('stroke', chartColor);

    const tick = svg
      .append('g')
      .attr('transform', `translate(0, ${height})`)
      .call(axisBottom(xScale).ticks(timeHour.every(1), '%H'))
      .selectAll('.tick')
      .style('transition', '.2s');

    tick.selectAll('text').attr('fill', '#A1A1A1');

    tick.selectAll('line').remove();

    tick
      .append('circle')
      .attr('r', '1.5')
      .style('fill', '#A1A1A1')
      .attr('cy', '0');

    svg
      .selectAll('.tick')
      .append('circle')
      .attr('r', 2)
      .style('fill', chartColor)
      .attr('cy', (x, i) => -height + yScale(parsedData[0].values[i].value));

    const setFade = (selection, opacity) => {
      selection.style('opacity', opacity);
    };
    const mouseover = (event, elements) => {
      selectAll(elements).filter(':not(:hover)').call(setFade, 2);
    };

    tick.on('mouseover', mouseover);

    const tickHorizontal = svg
      .append('g')
      .attr('transform', `translate(0, 0)`)
      .call(axisLeft(yScale).ticks(4))
      .selectAll('.tick')
      .style('transition', '.2s');

    tickHorizontal.selectAll('text').attr('fill', '#A1A1A1');
    tickHorizontal.selectAll('line').remove();

    svg.selectAll('.domain').style('stroke', '#A1A1A1');

    if (
      indexPoint !== undefined &&
      indexPoint <= dataLineChart.length &&
      indexPoint >= 1
    ) {
      const lastData = dataLineChart[dataLineChart.length - indexPoint];
      if (onSelectedDate) {
        onSelectedDate({
          timestamp: lastData.timestamp,
          value: lastData.value,
        });
      }

      const y = yScale(lastData.value);
      const x = xScale(parseTime(lastData.timestamp));

      svg
        .append('line')
        .attr('x1', x)
        .attr('x2', x)
        .attr('y1', y)
        .attr('y2', height)
        .attr('stroke', chartColor)
        .attr('stroke-width', '0.15rem');

      svg
        .append('circle')
        .attr('cy', y)
        .attr('cx', x)
        .style('fill', chartColor)
        .attr('r', '0.3rem');
    }

    return () => {
      svg.selectAll('*').remove();
    };
  }, [dataLineChart, indexPoint]);


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source