0

This is a modification of a previously asked question (In javascript, how do I extract the month from date string "yyyy-mm-dd" or timeStamp?), which was solved nicely by @mhodges.

Because of the nature of the modification, I thought it would be appropriate to just create a new question.

I have a database with certain logged events as json objects, each one with it's own JS millisecond timestamp and also a date string in the format "yyyy-mm-dd", as well as a minutes entry.

I'd like to use the timestamp as input into an algorithm which will count how many logs were entered in a given month and year.

I would also like the algorithm to sum the cumulative number of minutes were logged in a given month and year.

For example,

log1: {
    Date:"2017-05-24",
    TimeStamp:1495612800,
    Minutes: 15},
log2: {
    Date:"2017-05-19",
    TimeStamp:1495180800,
    Minutes: 45},
log3: {
    Date:"2017-04-24",
    TimeStamp:1493020800,
    Minutes:30},
log4: {
    Date:"2016-08-15",
    TimeStamp:1471248000,
    Minutes:75}

In this example, the algorithm would count that there are two logs in the month of May 2017, one log in the month of April 2017 and one log in the month of August 2016.

The algorithm would also return a sum of 60 minutes in the month of May 2017, 30 minutes in the month of April 2017 and 75 minutes in August 2016.

Any help with modifying the solution that @mhodges provided previously (see (In javascript, how do I extract the month from date string "yyyy-mm-dd" or timeStamp?)), into the appropriate nested output would be greatly appreciated!

I am having trouble modifying @mhodges solution to achieve it, but envision something like this:

{
  "2016":{
    "8": {
      occurrences: 1,
      minutes: 75
    }
  },
  "2017":{
    "4": {
      occurrences: 1,
      minutes: 30
    },
    "5": {
      occurrences: 2,
      minutes: 60
    }
  }
}

Thanks

3 Answers 3

1

Judging from your expected output, you probably want to use the date value instead of timestamp. You could loop through the logs and add up the minutes for each month.

It would look something like this:

var logs = [{
    Date: "2017-05-24",
    TimeStamp: 1495612800,
    Minutes: 15
  },
  {
    Date: "2017-05-19",
    TimeStamp: 1495180800,
    Minutes: 45
  },
  {
    Date: "2017-04-24",
    TimeStamp: 1493020800,
    Minutes: 30
  },
  {
    Date:"2016-08-15",
    TimeStamp:1471248000,
    Minutes:75
  }
];

var result = {};
for (var i = 0; i < logs.length; i++) {
  var year = logs[i].Date.slice(0, 4);
  var month = logs[i].Date.slice(5, 7);
  if (!result[year]) {
    result[year] = {};
  }
  if (!result[year][month]) {
    result[year][month] = {
      occurences: 1,
      minutes: logs[i].Minutes
    }
    continue;
  }
  result[year][month].occurences++;
  result[year][month].minutes += logs[i].Minutes;
}

console.log(result);

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a bunch for your solution. I chose it because it seemed to be the simplest solution for me to implement with my given setup that accomplished the goals I was trying to achieve. Although, I continued to use the timeStamp and just modified it a little bit.
1

Seems like a good problem to solve with the Array.prototype.map and Array.prototype.reduce as well as some of the built in Date methods.

const logs = [
  {
    Date:"2017-05-24",
    TimeStamp:1495612800,
    Minutes: 15
  },
  {
    Date:"2017-05-19",
    TimeStamp:1495180800,
    Minutes: 45
  },
  {
    Date:"2017-04-24",
    TimeStamp:1493020800,
    Minutes:30
  },
  {
    Date:"2016-08-15",
    TimeStamp:1471248000,
    Minutes:75
  }]

// mapping over the logs, transforming each so that we have data in the right form (ie. years, months, and minutes; occurences we'll get later).
const flat = logs.map(log => {
  const date = new Date(log.Date)
  return {
    year: date.getFullYear(),
    month: date.getMonth() + 1,
    minutes: log.Minutes, 
  }
})

const hierarchy = flat.reduce((hier, log) => {
  // As we're building the result, we need to init things if they don't already exist
  hier[log.year] = hier[log.year] || {}
  // The lowest level will have this form
  hier[log.year][log.month] = hier[log.year][log.month] || 
    {
      occurences: 0,
      minutes: 0
    }
  
  // Accumulate minutes and occurences as we go
  hier[log.year][log.month].minutes += log.minutes
  hier[log.year][log.month].occurences += 1

  return hier
}, {})

console.log(hierarchy)

1 Comment

Thank you for your solution. I think it definitely would have worked. I'm not sure how stack overflow really works but I am glad to give you a thumbs up or check mark if that helps.
0

Here's a crack at it.

let i = arr.length;
let obj = {};
while(i--){
  let [year, month, day] = arr[i].Date.split('-');

  //probably a better way of initializing a hashtree.
  if(!obj[year]){ obj[year] = {}; } 
  if(!obj[year][month]){ obj[year][month] = {}}

  let occur = obj[year][month]['occurences'] 
  let minutes = obj[year][month]['minutes'] 

  obj[year][month]['occurences'] = (occur === undefined) ? 1 : occur + 1;
  obj[year][month]['minutes'] = (minutes === undefined) ? arr[i].Minutes : arr[i].Minutes + minutes;
}

https://jsfiddle.net/25n4jo4e/

1 Comment

Thanks for your solution. It definitely was elegant and I may still modify my code to use it because I don't have to change too much. I'm not sure how stack overflow really works but I am glad to give you a thumbs up or check mark if that helps.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.