13

I have the array of Persian dates and I want to group dates by the week. for example, I have the following array:

[
    "1396-10-11 09:07:21",
    "1396-10-10 10:03:51",
    "1396-10-07 02:07:02",
    "1396-11-27 08:02:45",
    "1396-11-19 01:02:32",
    "1396-12-01 22:13:21",
    "1396-02-12 09:07:21",
    "1396-05-18 04:02:29",
    "1396-05-21 14:01:42",
    "1396-07-11 01:16:29"
]

and I want to groupBy dates by the week.

I wrote following code but not working good:

Array.prototype.groupBy = function(prop) {
  return this.reduce(function(groups, item) {
    var val = item[prop];
    groups[val] = groups[val] || [];
    groups[val].push(item);
    return groups;
  }, {});
}

const formatted = dates.map(elem => {
  return { 
    numberOfWeek: moment(elem.date, 'jYYYY-jMM-jDD').startOf('jMonth').jWeek(),
    date: moment(elem.date, 'jYYYY-jMM-jDD').format('jYYYY-jMM-jDD'), 
    score: elem.score 
  };
});
YouneL
  • 7,574
  • 2
  • 24
  • 48
Omid Nikrah
  • 2,307
  • 3
  • 12
  • 27
  • Can you show us what you have tried so far? Also for that array what is the desired output? – user3483203 Jan 03 '18 at 19:17
  • You should start by parsing the dates. Once you've shown you can do that, here's a pretty lengthy thread on determining the week of the year a day is in: https://stackoverflow.com/questions/6117814/get-week-of-year-in-javascript-like-in-php For grouping by, you can probably use an object with the week number as the keys. These are just ideas on how I'd do it. Like @chris said, please show us what you've tried and we can go from there. – wholevinski Jan 03 '18 at 19:23
  • @chris my code added – Omid Nikrah Jan 03 '18 at 19:29
  • There is an answer here that gets the year and week number for any date: [*Get week of year in JavaScript like in PHP*](https://stackoverflow.com/questions/6117814/get-week-of-year-in-javascript-like-in-php). However, you'll still need to correctly parse the input string to a Date. – RobG Jan 03 '18 at 22:43

2 Answers2

17

You can use moment().week() to get the week number of the year and then group by it, here is a working example, I used array.reduce to create a new object of dates grouped by the week number:

const dates = [
  "1396-10-11 09:07:21",
  "1396-10-10 10:03:51",
  "1396-10-07 02:07:02",
  "1396-11-27 08:02:45",
  "1396-11-19 01:02:32",
  "1396-12-01 22:13:21",
  "1396-02-12 09:07:21",
  "1396-05-18 04:02:29",
  "1396-05-21 14:01:42",
  "1396-07-11 01:16:29"
];

const groups = dates.reduce((acc, date) => {

  // create a composed key: 'year-week' 
  const yearWeek = `${moment(date).year()}-${moment(date).week()}`;
  
  // add this key as a property to the result object
  if (!acc[yearWeek]) {
    acc[yearWeek] = [];
  }
  
  // push the current date that belongs to the year-week calculated befor
  acc[yearWeek].push(date);

  return acc;

}, {});

console.log(groups);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.20.1/moment.min.js"></script>
YouneL
  • 7,574
  • 2
  • 24
  • 48
9

Another simple way of achieving the same with Lodash would be as follows:

const groupBy = require('lodash/groupBy');
const moment = require('moment');
const data = [
   "1396-10-11 09:07:21",
   "1396-10-10 10:03:51",
   "1396-10-07 02:07:02",
   "1396-11-27 08:02:45",
   "1396-11-19 01:02:32",
   "1396-12-01 22:13:21",
   "1396-02-12 09:07:21",
   "1396-05-18 04:02:29",
   "1396-05-21 14:01:42",
   "1396-07-11 01:16:29"
];

groupBy(data, (dt) => moment(dt).week());

Result is as follows:

{ 
  '7': [ '1396-02-12 09:07:21' ],
  '21': [ '1396-05-18 04:02:29', '1396-05-21 14:01:42' ],
  '29': [ '1396-07-11 01:16:29' ],
  '41': [ '1396-10-07 02:07:02' ],
  '42': [ '1396-10-11 09:07:21', '1396-10-10 10:03:51' ],
  '47': [ '1396-11-19 01:02:32' ],
  '49': [ '1396-11-27 08:02:45', '1396-12-01 22:13:21' ] 
}
Sohail
  • 4,306
  • 2
  • 36
  • 40