在nodejs应用程序中,我有一个事件对象数组,格式如下:
eventsArray = [ {id: 1, date: 1387271989749 }, {id:2, date: 1387271989760}, ... ]
eventsArray具有可变长度的n个元素,假设我选择时间参考为巴黎时间,我希望能够按天,周或月分组元素:
groupedByDay = {
2012: { ... },
2013: {
dayN : [{id: a0, date: b0}, {id: a1, date: b1}, {id: a2, date: b2 }],
dayN+1: [{id: a3, date: b3}, {id: a4, date: b4}, {id: a5, date: b5 }],
...
},
2014: { ... }
}
groupedByWeek = {
2012: { ... }
2013: {
weekN: [{id: a0, date: b0}, {id: a1, date: b1}, {id: a2, date: b2 }],
weekN+1: [{id: a3, date: b3}],
....
},
2014: { ... }
}
groupedByMonth = {
2012: { ... },
2013: {
monthN: [ {id: a0, date: b0 }, {id: a1, b1}, {id: a2, b2}, {id: a3, b3 }],
monthN+1: [ {id: a4, date: b4 }, {id: a5, b5}, {id: a6, b6}],
...
},
2014: { ... }
}
在操作unix时间戳方面经验很少,我想知道如何做到这一点,或者是否有一个npm模块可以使这更容易。
答案 0 :(得分:33)
上述所有解决方案都是大量纯粹的JS,香草解决方案。如果您可以使用几个库,那么lodash和moment可以一起用于简单的一行:
var groupedResults = _.groupBy(results, function (result) {
return moment(result['Date'], 'DD/MM/YYYY').startOf('isoWeek');
});
Mon Jul 25 2016 00:00:00 GMT+0100
这将导致一个在本周开始时键入的数组,例如moment()
。我相信你可以找出如何扩展它以获得数月,数年等等。
评论中提到,这并没有直接回答问题,因为原文使用UTC时间戳而不是格式化日期。在这种情况下,您应该使用moment(1387271989749).startOf('isoWeek');
而不使用第二个参数:
moment.unix(yourTimestamp).startOf('isoWeek');
或者如果使用UNIX时间戳,如下所示:
Commit Message
...虽然这已经开始从问题中进一步深入到Moment文档中,如果您想使用此方法,我建议您阅读。
答案 1 :(得分:12)
这是我的解决方案。请记住,自纪元以来,日,周和月都与原点相关:
eventsArray = [ {id: 1, date: 1387271989749 }, {id:2, date: 1387271989760} ];
byday={};
byweek={};
bymonth={};
function groupday(value, index, array)
{
d = new Date(value['date']);
d = Math.floor(d.getTime()/(1000*60*60*24));
byday[d]=byday[d]||[];
byday[d].push(value);
}
function groupweek(value, index, array)
{
d = new Date(value['date']);
d = Math.floor(d.getTime()/(1000*60*60*24*7));
byweek[d]=byweek[d]||[];
byweek[d].push(value);
}
function groupmonth(value, index, array)
{
d = new Date(value['date']);
d = (d.getFullYear()-1970)*12 + d.getMonth();
bymonth[d]=bymonth[d]||[];
bymonth[d].push(value);
}
eventsArray.map(groupday);
eventsArray.map(groupweek);
eventsArray.map(groupmonth);
答案 2 :(得分:3)
扩展@ user568109的答案,这是正确的并且已经投票,这里有一个功能完成所有,有一个更大的数组用于演示' s缘故:
// Group by time period - By 'day' | 'week' | 'month' | 'year'
// ------------------------------------------------------------
var groupByTimePeriod = function (obj, timestamp, period) {
var objPeriod = {};
var oneDay = 24 * 60 * 60 * 1000; // hours * minutes * seconds * milliseconds
for (var i = 0; i < obj.length; i++) {
var d = new Date(obj[i][timestamp] * 1000);
if (period == 'day') {
d = Math.floor(d.getTime() / oneDay);
} else if (period == 'week') {
d = Math.floor(d.getTime() / (oneDay * 7));
} else if (period == 'month') {
d = (d.getFullYear() - 1970) * 12 + d.getMonth();
} else if (period == 'year') {
d = d.getFullYear();
} else {
console.log('groupByTimePeriod: You have to set a period! day | week | month | year');
}
// define object key
objPeriod[d] = objPeriod[d] || [];
objPeriod[d].push(obj[i]);
}
return objPeriod;
};
var eventsArray = [{ id: 1, date: 1317906596 }, { id: 2, date: 1317908605 }, { id: 3, date: 1317909229 }, { id: 4, date: 1317909478 }, { id: 5, date: 1317909832 }, { id: 6, date: 1317979141 }, { id: 7, date: 1317979232 }, { id: 8, date: 1317986965 }, { id: 9, date: 1318582119 }, { id: 10, date: 1318595862 }, { id: 11, date: 1318849982 }, { id: 12, date: 1318855706 }, { id: 13, date: 1318929018 }, { id: 14, date: 1318933265 }, { id: 15, date: 1318940511 }, { id: 16, date: 1318945096 }, { id: 17, date: 1319017541 }, { id: 18, date: 1319527136 }, { id: 19, date: 1318582119 }, { id: 20, date: 1318595862 }, { id: 21, date: 1318582119 }, { id: 22, date: 1318595862 }, { id: 23, date: 1319713399 }, { id: 24, date: 1320053428 }, { id: 25, date: 1320333481 }, { id: 26, date: 1320832755 }, { id: 27, date: 1321012378 }, { id: 28, date: 1321280993 }, { id: 29, date: 1321347659 }, { id: 30, date: 1321350476 }, { id: 31, date: 1321369307 }, { id: 32, date: 1321369614 }, { id: 33, date: 1321610123 }, { id: 34, date: 1321613205 }, { id: 35, date: 1321617250 }, { id: 36, date: 1321626603 }, { id: 37, date: 1321865808 }, { id: 38, date: 1321876609 }, { id: 39, date: 1321877598 }, { id: 40, date: 1321877832 }, { id: 41, date: 1321953322 }, { id: 42, date: 1322061969 }, { id: 43, date: 1322142603 }, { id: 44, date: 1322211686 }, { id: 45, date: 1322213793 }, { id: 46, date: 1322214569 }, { id: 47, date: 1322482817 }, { id: 48, date: 1322663742 }, { id: 49, date: 1322664267 }, { id: 50, date: 1322747231 }, { id: 51, date: 1322819964 }, { id: 52, date: 1323358224 }, { id: 53, date: 1323681272 }, { id: 54, date: 1323695093 }, { id: 55, date: 1323696589 }, { id: 56, date: 1323763763 }, { id: 57, date: 1322819964 }, { id: 58, date: 1323681272 }, { id: 59, date: 1323851164 }, { id: 60, date: 1323853123 }, { id: 61, date: 1323854271 }, { id: 62, date: 1323858072 }, { id: 63, date: 1325690573 }, { id: 64, date: 1325751893 }, { id: 65, date: 1325760204 }, { id: 66, date: 1325769098 }, { id: 67, date: 1325769981 }, { id: 68, date: 1325771632 }, { id: 69, date: 1325776473 }, { id: 70, date: 1325837346 }, { id: 71, date: 1326110199 }, { id: 72, date: 1326793097 }, { id: 73, date: 1326878182 }, { id: 74, date: 1326881341 }, { id: 75, date: 1326975873 }, { id: 76, date: 1326985667 }, { id: 77, date: 1327047585 }, { id: 78, date: 1327062945 }, { id: 79, date: 1327063660 }, { id: 80, date: 1327322844 }, { id: 81, date: 1327326904 }, { id: 82, date: 1327329215 }, { id: 83, date: 1327397042 }, { id: 84, date: 1327399839 }, { id: 85, date: 1327401818 }, { id: 86, date: 1327407161 }, { id: 87, date: 1327419420 }, { id: 88, date: 1327570243 }, { id: 89, date: 1327578536 }, { id: 90, date: 1327584554 }, { id: 91, date: 1327914616 }, { id: 92, date: 1327917019 }, { id: 93, date: 1327931685 }, { id: 94, date: 1327933025 }, { id: 95, date: 1327934772 }, { id: 96, date: 1327947074 }, { id: 97, date: 1328626734 }, { id: 98, date: 1328626734 }, { id: 99, date: 1330070074 }, { id: 100, date: 1330073135 }, { id: 101, date: 1330073259 }, { id: 102, date: 1330332445 }, { id: 103, date: 1330351925 }, { id: 104, date: 1330420928 }, { id: 105, date: 1330423209 }, { id: 106, date: 1330437337 }, { id: 107, date: 1330439446 }];
var objPeriodDay = groupByTimePeriod(eventsArray, 'date', 'day');
var objPeriodWeek = groupByTimePeriod(eventsArray, 'date', 'week');
var objPeriodMonth = groupByTimePeriod(eventsArray, 'date', 'month');
var objPeriodYear = groupByTimePeriod(eventsArray, 'date', 'year');
console.log(objPeriodDay);
console.log(objPeriodWeek);
console.log(objPeriodMonth);
console.log(objPeriodYear);
这里a fiddle to go with it(您必须打开控制台才能看到输出)。
正如您在小提琴中看到的那样,4个对象的关键如下:
objPeriodDay
:自1970年1月1日以来的日期编号objPeriodWeek
:相对于1970年1月1日第一周的周数objPeriodMonth
:1970年1月1日以来的月份数objPeriodYear
:年份请注意,所有这四种变体都会为您提供 唯一 键。例如,月份会给你&#34; 2011年12月&#34; (以1970年1月1日以来的月份形式),而不只是&#34; Dec&#34;。
答案 3 :(得分:2)
我会做这样的事情:
var item,
i = 0,
groups = {},
year, day;
while (item = eventsArray[i++]) {
item = new Date(item.date);
year = item.getFullYear();
day = item.getDate();
groups[year] || (groups[year] = {}); // exists OR create {}
groups[year][day] || (groups[year][day] = []); // exists OR create []
groups[year][day].push(item);
}
此版本仅按日期对项目进行分组,但您可以使用相应的函数轻松获得使用item.getDate()
替换getWeek()
的数周和数月的相同结果:
getMonth()
:https://stackoverflow.com/a/6117889/1636522。答案 4 :(得分:1)
另一个使用 dayjs 库的实现
var dayjs = require('dayjs')
function groupTimesBy(theList, unit = 'day', timeParamName = 'create_time'){
var toReturn = {};
for(let listItem of theList) {
const paramName = dayjs.unix(listItem[timeParamName]).startOf(unit).unix();
if(toReturn[paramName] == null) {
toReturn[paramName] = [];
}
toReturn[paramName].push(listItem);
}
return toReturn;
}
let list = [{'time':1609104570}, {'time':1609104570}];
let byDay = groupTimesBy(list, 'day', 'time');
let byWeek = groupTimesBy(list, 'week', 'time');
let byMonth = groupTimesBy(list, 'month', 'time');
let byYear = groupTimesBy(list, 'year', 'time');
答案 5 :(得分:0)
这样的事情可能接近你所需要的。
Javascript日期有getFullYear
,getDate
和getMonth
个函数(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date),您还可以查看此SO帖子(Convert a Unix timestamp to time in JavaScript)。
这里的基本方法(安排)按年度建立哈希值,然后按日期和月份建立哈希值。
此代码不执行一周。你的意思是一年中哪个星期或哪个月?我怀疑你可以编写自己的日期方法来获取该数字,然后按照下面的模式获取你想要的所有数据。您可以从JS(getDay
)获取一周中的某一天。我不确定你想如何计算一周,但这种方法可能有所帮助。
我在浏览器中运行此代码(在初始化一组虚假的eventsArray之后),但我怀疑它会转换为节点就好了。
如果您愿意,您应该正确地命名该函数,并且可以将所有方法移动到对象原型中。
希望这有帮助
var groupEvents = function(eventsArray) {
this.dates = eventsArray;
this.arranged = {};
this.monthKey = function(month) {
return 'month' + month;
};
this.dayKey = function(month) {
return 'day' + month;
};
this.getYear = function(year) {
this.arranged[year] = this.arranged[year] || {}
return this.arranged[year]
};
this.getMonth = function(month, year) {
var y = this.getYear(year);
var k = this.monthKey(month);
y[k] = y[k] || [];
return y[k]
};
this.getDate = function(day, year) {
var y = this.getYear(year);
var k = this.dayKey(day);
y[k] = y[k] || [];
return y[k]
};
this.addToMonth = function(info, month, year) {
var y = this.getMonth(month,year);
y.push(info);
};
this.addToDay = function(info, day, year) {
var y = this.getDate(day,year);
y.push(info);
};
this.breakdownDate = function(date) {
return {
month: date.getMonth(),
day: date.getDate(),
year: date.getFullYear()
};
}
/** grab a date, break it up into day, month year
and then categorize it */
this.arrange = function() {
if(!this.arranged.length) {
var ii = 0;
var nn = this.dates.length;
for(; ii < nn; ++ii ) {
var el = this.dates[ii];
var date = new Date(el.date * 1000);
var parsed = this.breakdownDate(date);
this.addToMonth(el, parsed.month, parsed.year);
this.addToDay(el, parsed.month, parsed.year);
}
}
return this.arranged;
};
return this;
};
if(eventArray.length) {
var events = new groupEvents(eventArray);
var arranged = events.arrange();
console.log(arranged);
}