Sort and transform data based on the specific week intervals within the month

I have a set of objects, each containing four properties (id, start, end, and amount).

Using this data, I generate a new set of objects with the following attributes: date, duration, and amount. The date corresponds to the timestamp of the start property, while the duration represents the time difference in minutes between the start and end timestamps.

Next, I define two variables representing the selected month and year. I then filter the date array based on these chosen month and year values. For instance, if month 11 is chosen, only objects with dates from November would be included, and the same applies to the year. This results in a list of days corresponding to the selected month and year.

const arrayOfDates = [
    {
        id: 1,
        start: '2021-12-01T12:10:56+0000',
        end: '2021-12-01T12:00:56+0000',
        amount: 10
    },
    {
        id: 2,
        start: '2021-12-03T11:10:56+0000',
        end: '2021-12-03T12:45:56+0000',
        amount: 4
    },
    {
        id: 3,
        start: '2021-12-07T09:10:56+0000',
        end: '2021-12-07T09:25:56+0000',
        amount: 8
    },
    {
        id: 4,
        start: '2021-11-24T11:10:56+0000',
        end: '2021-11-24T11:25:56+0000',
        amount: 8
    }
]

const selectedMonth = 12
const selectedYear = 2021

const mapped = arrayOfDates.map((el) => ({
    date: new Date(el.start).toLocaleDateString('en-CA'),
    duration: new Date(new Date(el.end).getTime() - new Date(el.start).getTime()).getMinutes(),
    amount: el.amount
}))

const filteredBySelectedDate = mapped.filter((el) => {
    var [year, month] = el.date.split('-')
    return selectedMonth === +month && selectedYear === +year;
})

const mappedByDays = filteredBySelectedDate

In addition to displaying elements by day as currently done, I intend to enhance the filteredBySelectedDate array by grouping entries into weeks within the month. This means creating an array structure like:

const mappedByWeeks = [
    {
        interval: '12/01 - 12/04',
        duration: 85,
        amount: 14
    },
    {
        interval: '12/05 - 12/11',
        duration: 15,
        amount: 8
    }
]

Answer №1

To achieve this goal, follow these steps: Firstly, establish the known start and end days for each week of the month using weekTransitionDays. Secondly, identify the week to which an entry belongs with getWeekIndex. Lastly, combine entries for the same week with groupByWeek.

Edit

Included a utility function for generating interval text.

const arrayOfDates = [{
    id: 1,
    start: '2021-12-01T12:10:56+0000',
    end: '2021-12-01T12:00:56+0000',
    amount: 10
  },
  {
    id: 2,
    start: '2021-12-03T11:10:56+0000',
    end: '2021-12-03T12:45:56+0000',
    amount: 4
  },
  {
    id: 3,
    start: '2021-12-07T09:10:56+0000',
    end: '2021-12-07T09:25:56+0000',
    amount: 8
  },
  {
    id: 4,
    start: '2021-11-24T11:10:56+0000',
    end: '2021-11-24T11:25:56+0000',
    amount: 8
  }
];

const selectedMonth = 12;
const selectedYear = 2021;

const weekTransitionDays = [];
const firstDayOfMonth = (new Date(selectedYear, selectedMonth - 1, 1)).getDay();
const daysInMonth = (new Date(selectedYear, selectedMonth, 0)).getDate();

const getInterval = (start, end) => {
  if (start < 10) {
    start = "0" + start;
  }
  if (end < 10) {
    end = "0" + end;
  }
  start = selectedMonth + "/" + start;
  end = selectedMonth + "/" + end;
  return start + ' - ' + end;
};

let start = 1;
if (firstDayOfMonth !== 0) {
  let end = start + 6 - firstDayOfMonth;
  const interval = getInterval(start, end);
  weekTransitionDays.push({
    start,
    end,
    interval
  });
  start = end;
}

while (start < daysInMonth) {
  let end;
  if (start + 1 < daysInMonth) {
    start++;
  } else {
    break;
  }
  if (start + 6 < daysInMonth) {
    end = start + 6;
  } else {
    break;
  }
  const interval = getInterval(start, end);
  weekTransitionDays.push({
    start,
    end,
    interval
  });
  start = end;
}

if (weekTransitionDays.at(-1).end !== daysInMonth) {
  const end = daysInMonth;
  const interval = getInterval(start, end);
  weekTransitionDays.push({
    start,
    end,
    interval
  });
}

const getWeekIndex = entry => {
  const entryStart = new Date(entry.start).getDate();
  for (let i = 0; i < weekTransitionDays.length; i++) {
    if (weekTransitionDays[i].start <= entryStart && entryStart <= weekTransitionDays[i].end) {
      return i;
    }
  }
  // Raise error if start date doesn't match transition days
  throw new Error("entry.start mismatch with transition days: \n" + JSON.stringify(entry) + "\n" + JSON.stringify(weekTransitionDays));
};

const mapped = arrayOfDates.map((el) => ({
  date: new Date(el.start).toLocaleDateString('en-CA'),
  duration: new Date(new Date(el.end).getTime() - new Date(el.start).getTime()).getMinutes(),
  weekIndex: getWeekIndex(el),
  amount: el.amount
}));

const filteredBySelectedDate = mapped.filter((el) => {
  var [year, month] = el.date.split('-');
  return selectedMonth === +month && selectedYear === +year;
});

const groupByWeek = () => {
  const obj = {};
  filteredBySelectedDate.forEach(entry => {
    if (!obj.hasOwnProperty(entry.weekIndex)) {
      obj[entry.weekIndex] = {
        interval: weekTransitionDays[entry.weekIndex].interval,
        duration: 0,
        amount: 0
      };
    }
    obj[entry.weekIndex].duration += entry.duration;
    obj[entry.weekIndex].amount += entry.amount;
  });
  return Object.values(obj);
};

const mappedByDays = filteredBySelectedDate;
const groupedByWeek = groupByWeek(mapped);

console.log(groupedByWeek);

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

How to locate the index of a specific item or multiple items within a JsonArray?

Can you help me determine which city is closest to Vancouver: Victoria, Washington or Texas? Once I find the shortest distance, how can I identify which destination address this value corresponds to? { "destination_addresses" : [ "Victoria, BC, C ...

I am in search of a specialized 3D camera with a unique effect

I am seeking assistance with animating a camera to replicate or closely resemble the effect seen in this demo: Any help would be greatly appreciated. ...

Display a jQuery alert when an AJAX post request exceeds its timeout limit

I have been working on creating a feature to notify users when their $.post() request times out. To achieve this, I have implemented the following code snippet: //when ajax request start show overlay $(document).ajaxStart(function(){ ...

Showing an individual image when a particular list item is clicked using jquery

I have created an image slider that automatically transitions between images. However, I would like to have a specific image displayed when a particular list item is clicked in the round buttons below. For example, if the slider is showing the 5th image a ...

Blur images on parent div when hovering using javascript

After some extensive searching, I came across a few helpful explanations on how to achieve my desired outcome. By combining them, I was able to get everything working smoothly with the hover effect over the image itself. However, when I attempted to trigge ...

Utilizing ES6 Functions to Transform Objects into Arrays

Is there a way to convert a JavaScript object into an array using ECMAScript-6? Take, for instance: var inputObj = {a:'foo', b:[1,2,3], c:null, z:55}; The desired outcome would look like this: ['foo', [1,2,3], null, 55] The seque ...

Experiencing excessive CPU usage while utilizing a progress bar in Angular

Whenever I try to load a page with 2 progress bars, my CPU usage goes through the roof... I decided to investigate and found that once I removed them, the site's speed improved significantly. Here's a code snippet of one of the progress bars: ...

Accessing the parent scope from a directive within a nested ng-repeat in AngularJs

Seeking guidance on accessing the parent scope within a directive nested in an ng-repeat. Here is an example: <div ng-app="myApp" ng-controller="myCtrl"> <div ng-repeat="section in sections"> {{section.Name}} <div ng-rep ...

The angular-block-ui feature fails to run my HTML code as a personalized message

I'm looking to enhance my UI by implementing a blocking feature with a spinner display. My attempt involved the following code: blockUI.start("<div class='dots-loader'>Minions are Working!</div>"); // code for fetching data ...

Issue with the stack: unable to add a few characters to the array

I've encountered an issue with implementing a stack using arrays. The problem arises when attempting to push more than one character at a time. I have initialized variables using a 'struct' in order to push multiple characters in the form of ...

Tips for creating unique names for JSON data modification functions

I have some data stored in JSON format that I need to slightly rearrange before sending it to the client. What should I name the function responsible for this reordering? Is serializeSomething a suitable choice? From what I understand, serialization invo ...

What is the best method for replacing the current page in an Ionic app?

I am facing an issue with the following navigation flow: User lands on the Contacts page -> clicks on a button to navigate to the NewContact page using navController.push() method -> from there, user is directed to the ContactCreated page. How can ...

Array - Modifications do not pass down to the child component

I am observing the following structure in the code: <div id="join-container"> <join-chain id="my-join-chain" [selectedColumn]="selectedColumn" (updatedStatements)=onUpdatedStatements($event)> </join-chain> <tile-ca ...

Static files compiled from Django 2 and Angular 6 consistently redirect to the static directory

I am currently working on a Django 2 + Angular 6 project. As part of my build process, I move the compiled JS files into Django's static folder. However, I encounter an issue whenever I try to access a link, such as , the browser automatically redire ...

What causes async / await function to be executed twice?

I am currently developing a node.js application using express. In this project, I have implemented a regular router that performs the following tasks: It searches for the myID in the DB, If the myID is found, it attempts to execute the addVisit() functio ...

A peculiar issue is occurring in Vue.js where a value within a v-for loop seems to be losing association with the intended array

During my third day of working with Vue.js, I decided to create a basic application for requesting car keys in a service department. Although I am aware that there are areas in the code that could be improved, I encountered a specific issue that I need ass ...

Combining Angular subscriptions to fetch multiple data streams

I am looking to retrieve the most recent subscription from a group of subscriptions. Whenever the value of my FormControl changes, I want to capture only the latest value after the user has finished typing. Below is the code snippet I am using - let cont ...

Displaying a single array alongside another in a single communication

I am trying to display the IDs from Array 1 next to the corresponding IDs from Array 2. The two arrays I am working with are called memberIDs and rolesIDs. The memberIDs array contains the member IDs in a voice channel, while the roleIDs array includes va ...

Modify the color of the components in Select from Material-UI

After reviewing numerous questions and answers on this topic, I have yet to find a suitable solution for my issue. Seeking guidance from the community for assistance. Utilizing the Select component from @mui/material to showcase the number of records per ...

What steps should I take to troubleshoot and resolve this PHP, AJAX, and JavaScript dilemma

Hey there, I'm new to PHP and currently working on creating a form with a dropdown list option that pulls data from my database. My goal is to have the selected option display the related details in the text field for the user. In my database, I have ...