Group List by Quarters
Groups monthly financial data by calendar quarters using the getQuarter()
method from
the date-fns
library. Each group includes individual monthly entries and an optional cumulative total for the quarter.
Useful for:
- Visualizing quarterly reports
- Aggregating financial or performance data
- Preparing charting datasets or grouped UI views
Steps:
groupDataByQuarter(data)
– Organizes data into a dictionary using keys like"2023-Q1"
based on thedate
field.initializeDates(groupedQuarters)
– Prepares a simplified structure listing quarters and associated month strings.initializeRestData(groupedQuarters)
– Flattens the quarterly structure into tax-specific groups, returning an array of metrics (profit
,profit_percent
) with their per-quarter values and totals.
This modular approach is helpful when formatting data for analytics dashboards or quarterly reports.
groupDataByQuarter
import { getQuarter, parseISO } from "date-fns";
// data
export const TaxEntitiesKeys = {
profit: "profit",
profit_percent: "profit_percent",
};
const mockTaxes = {
cumulative: [
{ date: "2023-01-31", profit: 1000, profit_percent: 100 },
{ date: "2023-02-28", profit: 2000, profit_percent: 200 },
{ date: "2023-04-30", profit: 3000, profit_percent: 250 },
],
report: [
{ date: "2023-01-31", profit: 300, profit_percent: 30 },
{ date: "2023-02-28", profit: 500, profit_percent: 50 },
{ date: "2023-04-30", profit: 700, profit_percent: 70 },
],
};
// data
// group by quarters
const groupDataByQuarter = (data) => {
const quarters = {};
// Group data into quarters based on their date
for (const monthData of data.report) {
const date = parseISO(monthData.date);
const year = date.getFullYear();
const quarter = getQuarter(date);
const key = `${year}-Q${quarter}`;
if (!quarters[key]) {
quarters[key] = { months: [], total: null };
}
quarters[key].months.push(monthData);
}
// Assign cumulative totals to their respective quarters
for (const totalData of data.cumulative) {
const date = parseISO(totalData.date);
const year = date.getFullYear();
const quarter = getQuarter(date);
const key = `${year}-Q${quarter}`;
if (quarters[key]) {
quarters[key].total = totalData;
}
}
return quarters;
};
const groupedQuarters = groupDataByQuarter(mockTaxes);
console.log(JSON.stringify({ groupedQuarters }, null, 2));
// group by quarters
// {
// groupedQuarters: {
// "2023-Q1": {
// months: [
// {
// date: "2023-01-31",
// profit: 300,
// profit_percent: 30,
// },
// {
// date: "2023-02-28",
// profit: 500,
// profit_percent: 50,
// },
// ],
// total: {
// date: "2023-02-28",
// profit: 2000,
// profit_percent: 200,
// },
// },
// "2023-Q2": {
// months: [
// {
// date: "2023-04-30",
// profit: 700,
// profit_percent: 70,
// },
// ],
// total: {
// date: "2023-04-30",
// profit: 3000,
// profit_percent: 250,
// },
// },
// },
// };
// dates
const initializeDates = (quarters) => {
const dates = [];
Object.entries(quarters).forEach(([dateKey, data]) => {
const [year, quarter] = dateKey.split("-Q").map(Number);
let yearEntry = dates.find((entry) => entry.year === year);
if (!yearEntry) {
yearEntry = { year, periods: [] };
dates.push(yearEntry);
}
yearEntry.periods.push({
months: data.months.map((month) => month.date),
quarter: `${quarter}`,
});
});
return dates;
};
console.log(
JSON.stringify({ dates: initializeDates(groupedQuarters) }, null, 2),
);
// dates
// {
// dates: [
// {
// year: 2023,
// periods: [
// {
// months: ["2023-01-31", "2023-02-28"],
// quarter: "1",
// },
// {
// months: ["2023-04-30"],
// quarter: "2",
// },
// ],
// },
// ],
// };
// rest data
const initializeRestData = (quarters) => {
return Object.keys(TaxEntitiesKeys).map((taxKey) => {
const taxKeyTyped = taxKey;
return {
title: taxKeyTyped,
periods: Object.entries(quarters).map(([_, data]) => ({
months: data.months.map((month) => month[taxKeyTyped]),
total: data.total ? data.total[taxKeyTyped] : null,
})),
};
});
};
console.log(
JSON.stringify({ restData: initializeRestData(groupedQuarters) }, null, 2),
);
// rest data
// {
// restData: [
// {
// title: "profit",
// periods: [
// {
// months: [300, 500],
// total: 2000,
// },
// {
// months: [700],
// total: 3000,
// },
// ],
// },
// {
// title: "profit_percent",
// periods: [
// {
// months: [30, 50],
// total: 200,
// },
// {
// months: [70],
// total: 250,
// },
// ],
// },
// ],
// };
Last updated on