Skip to Content
UtilsGroup List by Quarters

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:

  1. groupDataByQuarter(data) – Organizes data into a dictionary using keys like "2023-Q1" based on the date field.
  2. initializeDates(groupedQuarters) – Prepares a simplified structure listing quarters and associated month strings.
  3. 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