Chartjs-Customizing ChartJS labels to use text and dates

0👍

You could consolidate each data point by the first Monday of the week.

Now all you have is a category chart where you can choose your own formatting for the custom labels.

const ctx = document.getElementById('myChart');

const dateFormatter = new Intl.DateTimeFormat('en-US', {
  month: 'short',
  day: '2-digit'
});

const rawData = `
2023-05-28T12:00:00Z 1
2023-05-22T12:00:00Z 1
2023-05-21T12:00:00Z 2
2023-05-15T12:00:00Z 1
2023-05-14T12:00:00Z 1
2023-05-08T12:00:00Z 3
2023-05-07T12:00:00Z 2
2023-05-01T12:00:00Z 3
2023-04-30T12:00:00Z 6
2023-04-24T12:00:00Z 1
`;

// Ungrouped data
const parsedData = rawData.trim().split('\n').map((line) => {
  const [timestamp, value] = line.split(' ');
  return { x: new Date(timestamp), y: +value };
});

const findClosestMonday = (date) => {
  const closestMonday = new Date(date.getTime());
  while (closestMonday.getDay() !== 1) {
    closestMonday.setDate(closestMonday.getDate() - 1);
  }
  closestMonday.setHours(0);
  closestMonday.setMinutes(0);
  closestMonday.setSeconds(0);
  closestMonday.setMilliseconds(0);
  return closestMonday;
};

// Grouped by closest Monday
const consolidatedData = parsedData.reduce((groups, { x, y }) => {
  const key = findClosestMonday(x).toLocaleDateString();
  groups[key] = (groups[key] ?? 0) + y;
  return groups;
}, {});

const finalData = Object.entries(consolidatedData)
    .map(([timestamp, y]) => ({ x: new Date(timestamp), y }))
  .sort(({ x: x1 }, { x: x2 }) => x2 - x1); // DESC

const customLabels = finalData.map(({ x }) => {
  const curr = new Date(x.getTime());
  let label = dateFormatter.format(curr);
  curr.setDate(curr.getDate() + 6);
  label += ` - ${dateFormatter.format(curr)}`;
  return label;
});

new Chart(ctx, {
  type: 'bar',
  data: {
    labels: customLabels,
    datasets: [{
      label: 'Series',
      data: finalData,
      borderWidth: 1
    }]
  },
  options: {
    scales: {
      y: {
        beginAtZero: true
      }
    }
  }
});
<div>
  <canvas id="myChart"></canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

Leave a comment