web-dev-qa-db-ja.com

タイムスタンププロパティを持つオブジェクトを日、週、月でグループ化する方法は?

Nodejsアプリケーションでは、次のようにフォーマットされたイベントオブジェクトの配列があります。

eventsArray = [ {id: 1, date: 1387271989749 }, {id:2, date: 1387271989760}, ... ]

可変長のn要素を持つeventsArrayで、時間参照をパリ時間として選択した場合、要素を日、週、または月でグループ化できるようにしたいと思います。

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モジュールがあるのか​​と思いました。

24
Running Turtle

これが私の解決策です。エポック以降、日、週、月はOriginに関連していることに注意してください。

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);
12
user568109

上記のすべてのソリューションは、高額で純粋なJS、バニラソリューションです。いくつかのライブラリーを使用してもよい場合は、 lodash および moment を一緒に使用して、単純な1つのライナーを作成できます。

ES6

_let groupedResults = _.groupBy(results, (result) => moment(result['Date'], 'DD/MM/YYYY').startOf('isoWeek'));
_

古いJS

_var groupedResults = _.groupBy(results, function (result) {
  return moment(result['Date'], 'DD/MM/YYYY').startOf('isoWeek');
});
_

これにより、_Mon Jul 25 2016 00:00:00 GMT+0100_のような、週の初めをキーとする配列になります。あなたはそれを何ヶ月、何年など得るために拡張する方法を考え出すことができると確信しています。

RE:@SaintScottのコメント

オリジナルはフォーマットされた日付ではなくUTCタイムスタンプを使用しているため、これは質問に直接回答しないことはコメントで言及されました。この場合、2番目のパラメーターなしでmoment()を使用する必要があります。

_moment(1387271989749).startOf('isoWeek');
_

または、次のようにUNIXタイムスタンプを使用する場合:

_moment.unix(yourTimestamp).startOf('isoWeek');
_

...これは質問からさらに離れてモーメントのドキュメントにも入り始めていますが、この方法を使用したい場合は読むことをお勧めします。

42
Matt Fletcher

正しいと投票された@ user568109の答えを拡張して、ここにそれをすべて実行する1つの関数を示します。

// 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);

そして、これが それに伴うフィドル です(出力を表示するにはコンソールを開く必要があります)。

フィドルでわかるように、4つのオブジェクトのキーは次のようになります。

  • objPeriodDay:1970年1月1日からの日数
  • objPeriodWeek:1970年1月1日の最初の週を基準とした週番号
  • objPeriodMonth:1970年1月1日からの月数
  • objPeriodYear:年

これら4つのバリエーションはすべて、uniqueキーを提供することに注意してください。たとえば、Monthは、「Dec」だけでなく、「Dec 2011」(1970年1月1日からの月の形式)を提供します。

3

私はこのようなことをします:

_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()を適切な関数に置き換えて、数週間と数か月間同じ結果を簡単に得ることができます:

3
leaf

このようなものはおそらくあなたが必要としているものに近いでしょう。

JavaScriptの日付にはgetFullYeargetDategetMonth関数があります( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date )そして、このSO post( nixタイムスタンプをJavaScriptで時間に変換する )も確認してください。

ここでの基本的な方法(配置)は、年ごとに、次に日と月ごとにハッシュを構築します。

このコードは一週間行いません。 1年のどの週またはどの月を意味しますか?独自の日付メソッドを記述してその数値を取得し、以下のパターンに従って必要なすべてのデータを取得できると思います。 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);
}
0
mr rogers