What is the best way to organize an array of dates and calculate the total value for each day, 1 hour, 6 hours, 8 hours, week, month, and year

I have an array of dates that I need to group by year, month, week, day, 6 hours, 8 hours, and 1 hour, and then sum the values. Here is an example of the data:

const datesData = [
  { date: "2021-10-17T14:38:45.540Z", value: 2 },
  { date: "2021-09-16T14:36:46.540Z", value: 1 },
  { date: "2021-01-04T14:35:46.540Z", value: 2 },
  // more data...
]

I attempted to group the data using Moment.js and Lodash. You can see my code here.

However, when grouping by year, I faced issues with some years like 2018 and 2016 not being displayed in the result:

 [
  {
    "color": "Blue",
    "value": 6,
    "label": "2021"
  },
  // more results...
]

Here is the expected output for grouping by year:

[
      {
        "color": "Blue",
        "value": 6,
        "label": "2021"
      },
      // additional results including 2018 and 2016
    ]

Answer №1

To achieve this goal, you can utilize a standard 'group-by' approach using reduce, where data is accumulated into an object and then transformed into an array by employing Object.values().

A simple helper function named get_date_parts has been defined to parse the ISO date strings, which works well for basic grouping tasks. For more complex label formats, you can also use a Date object.

The example demonstrates year-based grouping, which can be adapted for other types of grouping with some adjustments for hour ranges.

const data = [{ x: '2021-10-17T14:38:45.540Z', y: 2 }, { x: '2021-09-16T14:36:46.540Z', y: 1 }, { x: '2021-01-04T14:35:46.540Z', y: 2 }, { x: '2021-01-01T14:30:46.540Z', y: 1 }, { x: '2020-02-01T06:28:47.520Z', y: 12 }, { x: '2020-02-01T07:28:47.520Z', y: 12 }, { x: '2019-04-13T10:19:20.034Z', y: 20 }, { x: '2018-01-01T09:09:19.134Z', y: 4 }, { x: '2017-01-01T12:09:19.034Z', y: 11 }, { x: '2016-01-02T12:10:20.034Z', y: 24 },];

function get_date_parts(iso_string) {
  const [year, month, day, hr, min, sec] = iso_string.split(/\D/g);

  return { year, month, day, hr, min, sec };
}

function group_by_year(arr) {
  return Object.values(
    arr.reduce((a, { x: date_string, y: value }) => {
      const { year } = get_date_parts(date_string);
      (a[year] ??= { color: 'Blue?', value: 0, label: year }).value += value;

      return a;
    }, {}),
  );
}

const grouped_by_year = group_by_year(data).sort((a, b) => +b.label - +a.label);

console.log(grouped_by_year);

You can also perform grouping by month, showcasing an alternative method to logical nullish assignment (??=) for initial assignments to a[key].

const data = [{ x: '2021-10-17T14:38:45.540Z', y: 2 }, { x: '2021-09-16T14:36:46.540Z', y: 1 }, { x: '2021-01-04T14:35:46.540Z', y: 2 }, { x: '2021-01-01T14:30:46.540Z', y: 1 }, { x: '2020-02-01T06:28:47.520Z', y: 12 }, { x: '2020-02-01T07:28:47.520Z', y: 12 }, { x: '2019-04-13T10:19:20.034Z', y: 20 }, { x: '2018-01-01T09:09:19.134Z', y: 4 }, { x: '2017-01-01T12:09:19.034Z', y: 11 }, { x: '2016-01-02T12:10:20.034Z', y: 24 },];

function get_date_parts(iso_string) {
  const [year, month, day, hr, min, sec] = iso_string.split(/\D/g);

  return { year, month, day, hr, min, sec };
}

function group_by_month(arr) {
  return Object.values(
    arr.reduce((a, { x: date_string, y: value }) => {
      const { year, month } = get_date_parts(date_string);
      const key = `${year}/${month}`;
      
      // added longhand version for logical nullish assignment
      if (a[key] === undefined) {
        a[key] = { color: 'Blue?', value: 0, label: key };
      }

      a[key].value += value;

      return a;
    }, {}),
  );
}

const grouped_by_month = group_by_month(data).sort((a, b) => b.label.localeCompare(a.label));

console.log(grouped_by_month);

If there are groupings not directly inherent in the dates, simple arithmetic calculations can be utilized.

function get_date_parts(iso_string) {
  const [year, month, day, hr, min, sec] = iso_string.split(/\D/g);

  return { year, month, day, hr, min, sec };
}

const date_string = '2020-02-07T07:28:47.520Z';

const { year, month, day, hr } = get_date_parts(date_string);

// Calculate week within the month
const week = Math.floor((parseInt(day, 10) - 1) / 7);
const week_label = `${year}/${month} - week ${week + 1}`;
console.log({ week_label, week });

// Determine hour range
const range_size = 8;
const range = Math.floor(parseInt(hr, 10) / range_size);
const range_start = `${(range * range_size).toString().padStart(2, '0')}:00`;
const range_end = `${(range * range_size + range_size).toString().padStart(2, '0')}:00`;
const range_label = `${day}/${month}/${year} ${range_start}-${range_end}`;

console.log({ range_label, range });

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for looping through a combined array containing two distinct sets of data in a table

I'm facing an issue with managing two different arrays: one for Users and another for Licensed Users. For example, let's say there are 20 users in the main array but only 6 of them are licensed users. Every licensed user is also included in the ...

Tips on attaching a suffix icon to a material-ui-pickers input box

Here is a snippet of my code: <Box p={6}> <Grid container spacing={2}> <Grid item xs={6}> <TimePicker autoOk label={t('checkIn')} value={time1} onChange={handlecheckIn} clearable /> </Grid> < ...

Implementing three identical dropdown menus using jQuery and HTML on a single webpage

It seems like I've tangled myself up in a web of confusion. I'm trying to have three identical dropdowns on a single page, each displaying clocks from different cities (so users can view multiple clocks simultaneously). However, whenever I update ...

Changing HTML content using escape characters in jQuery: A step-by-step guide

I am looking for a way to replace a portion of the html content using jquery. However, I am facing an issue with escape characters in both the original and replacing string, which is causing the html().replace function to not work as expected. Is there a s ...

I'm in the process of designing a Todo list platform, but I've hit a roadblock trying to figure out the best way to showcase and delete tasks

Having some trouble with creating an li element even after following the necessary steps. Any guidance and explanation would be greatly appreciated. Thank you Managing HTML and CSS is fine, but when it comes to JavaScript, I always seem to struggle. I und ...

Modify the nested object's two layers using the designated ID

In my Mother Model, there is a fixed structure where I manipulate cards on three array levels: starter, intermediate, and advanced. { cards: { starter: [], intermediate: [], advanced: [ {Object}, {Object}, {Object} ] }, } The objects withi ...

JavaScript function trying to send a POST request to API

I'm encountering an issue when attempting to execute an API GET request using JavaScript's built-in XMLHttpRequest function. I'm perplexed by why this functionality is failing to operate properly. function getStats(username){ const request ...

A Guide on Using Puppeteer to Extract the Value from an Invisible Input Element

import puppeteer from 'puppeteer' async function fetchSteamID(url) { try { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto(url); const element = await page.wait ...

Having various Collada scenes in Three.js animation may not be compatible

I'm having trouble animating multiple models in Collada format (knight.dae & archer.dae). The issue is that I can't seem to get them all to animate properly, specifically in an idle state with only 2-3 frames. When I load the scene, I end up with ...

Ionic Angular 2 Form Development

Recently, I've encountered an issue while trying to submit a form using Ionic in Angular. <form method="post" class="form-horizontal" action="https://localhost:44370/Account/ExternalLogin"> <div> <p> <!-- ...

Sequence of HTML elements arranged in a stack

Recently, I came across a useful jQuery tutorial called "jQuery for Absolute Beginners: Day 8". In this tutorial, there is an interesting code snippet that caught my attention: $(function() { $('.wrap').hover(function() { $(this).childre ...

Establishing seamless transitions between various interfaces within my application

Hello everyone, I am developing an app in React Native and I have successfully implemented a login system. However, I am facing issues with routing between different screens. For example, I have distinct flows such as the signup flow: 1) User enters phone ...

Encountering issues when attempting to invoke a function from an external file in Angular4

When attempting to call a method from an external file using Angular4, I am encountering the following error: Error: ERROR in src/app/about/about.component.ts(22,9): error TS2304: Cannot find name 'checkJS'. Below is the code I am working with ...

What is an elegant way to showcase a large 2D array in a WPF application, similar to the layout of Excel spreadsheet

Currently, I'm facing a challenge involving the display of a 2-dimensional array within a WPF window. The size of the array can reach up to 360*720 dimensions. Attempting to use a DataTable bound to a DataGrid proved to be inefficient, as it resulted ...

`How can I retrieve scope variables from a directive in angular.js?`

In my AngularJS web application, I have created a custom filter to search through posts: app.filter('myfilter', function() { return function(postList, term) { var out = []; if(!postList) return out; if(!term) return postList; var i ...

Encountering a parsing error while trying to fetch and parse XML using

I'm looking to retrieve XML data from the following URL using JQuery Ajax When accessing via browser, this is displayed: This XML file does not appear to have any style information associated with it. The document tree is shown below. <puco> ...

React not properly updating state variable with setState

I am facing an issue while attempting to assign the response data from an API call to a state variable. There is an array called 'divisions' in the 'responseJson' object that I am trying to set to the 'divisions' array in the ...

The response data from Axios remains undefined even after a successful request

function verifyPassword() { let pass = document.getElementById("password").value let emailAddr = document.getElementById("email").value Service.confirmLoginPassword(emailAddr, pass).then(response => { result = re ...

Preserving KendoGrid Selection Status During Navigation Between Pages

When using kendoGrid, I encounter an issue where the selected product ID does not persist across different pages. Initially, when the grid is loaded, the corresponding row is selected based on the productID. However, after unchecking the product ID on the ...

Tips for organizing components in jQuery Mobile

Displaying a survey creation form: <!-- HTML structure --> <div data-role="page" data-theme="b"> <div data-role="header"> <h1> Create Survey </h1> </div> <div id="main" data ...