Reputation: 2482
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
};
});
Upvotes: 18
Views: 19169
Reputation: 400
If you're searching for a vanilla JavaScript solution like I was, I managed to adapt the accepted answer to replace moment.js with pure vanilla code. I also had to make use of the suggesstion of a PersionDate class from this post in another question.
For gregorian calender you simply replace PersianDate
by the default Date
class
class PersianDate extends Date {
constructor(...args) {
super(...args);
}
toLocaleDateString = () => super.toLocaleDateString('fa-IR-u-nu-latn');
getParts = () => this.toLocaleDateString().split("/")
getDay = () => super.getDay() === 6 ? 0 : super.getDay() + 1
getDate = () => this.getParts()[2];
getMonth = () => this.getParts()[1] - 1;
getYear = () => this.getParts()[0];
getMonthName = () => this.toLocaleDateString("fa-IR", { month: 'long' });
getDayName = () => this.toLocaleDateString("fa-IR", { weekday: 'long' });
}
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, curr) => {
const date = new PersianDate(curr);
const startOfYearDate = new PersianDate(date.getFullYear(), 0, 1);
const weekOfYear = Math.ceil(Math.floor((date.getTime() - startOfYearDate.getTime()) /
(24 * 60 * 60 * 1000)) / 7);
// create a composed key: 'year-week'
const yearWeek = `${date.getFullYear()}-${weekOfYear}`;
// 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(curr);
return acc;
}, {});
console.log(groups);
Upvotes: 0
Reputation: 8351
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>
Upvotes: 24
Reputation: 4586
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' ]
}
Upvotes: 11