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>
Source:stackexchange.com