Find last document of the day for the last 7 days - javascript

I am adding entries to a schema every hour in order to track growth over the course of days while maintaining a current score for the current day. Now I would like to be able to pull the most recent record for each day for the past week. The results would be 6 records at or around midnight for 6 days previous and the 7th being the latest for the current day.
Here is my schema:
var schema = new Schema({
aid: { type: Number }
, name: { type: String }
, score: { type: Number }
, createdAt: { type: Date, default: Date.now() }
})
Edit
I've tried using this static, but it pulls the exact same record 7 times
schema.statics.getLastWeek = function(name, fn) {
var oneday = 60 * 60 * 24
, now = Date.now()
, docs = []
for (var i = 1; i <= 7; i++) {
this.where('name', new RegExp(name, 'i'))
.where('createdAt')
.gte(now - (i * oneday))
.desc('createdAt')
.findOne(function(err,doc){
docs.push(doc)
})
}
}
If I were using SQL I would do a subquery selecting MAXDATE and join it to my main query in order to retrieve the results I want. Anyway to do this here?

Kristina Chodorow gives a detailed recipe for this exact task in her book MongoDB: The Definitive Guide:
Suppose we have a site that keeps track of stock prices. Every few
minutes from 10 a.m. to 4 p.m., it gets the latest price for a stock,
which it stores in MongoDB. Now, as part of a reporting application,
we want to find the closing price for the past 30 days. This can be
easily accomplished using group.
I'm not familiar with Mongoose, however I've tried to adapt her example to your case below. Note I changed the createdAt default property from a value to a function and added an extra field datestamp to your schema:
var oneday = 24 * 60 * 60;
var schema = new Schema({
aid: { type: Number }
, name: { type: String }
, score: { type: Number }
// default: is a function and called every time; not a one-time value!
, createdAt: { type: Date, default: Date.now }
// For grouping by day; documents created on same day should have same value
, datestamp: { type: Number
, default: function () { return Math.floor(Date.now() / oneday); }
}
});
schema.statics.getLastWeek = function(name, fn) {
var oneweekago = Date.now() - (7 * oneday);
ret = this.collection.group({
// Group by this key. One document per unique datestamp is returned.
key: "datestamp"
// Seed document for each group in result array.
, initial: { "createdAt": 0 }
// Update seed document if more recent document found.
, reduce: function(doc, prev) {
if (doc.createdAt > prev.createdAt) {
prev.createdAt = doc.createdAt;
prev.score = doc.score;
// Add other fields, if desired:
prev.name = doc.name;
}
// Process only documents created within past seven days
, condition: { "createdAt" : {"$gt": oneweekago} }
}});
return ret.retval;
// Note ret, the result of group() has other useful fields like:
// total "count" of documents,
// number of unique "keys",
// and "ok" is false if a problem occurred during group()
);

A solution is to use group() to groups records by day. It's fancy, slow and can be blocking (meaning nothing else can run at the same time), but if your record set isn't too huge it's pretty powerful.
Group: http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Group
As for mongoose, I'm not sure if it supports group() directly, but you can use the node-mongodb-native implementation, by doing something like this (pseudo-code, mostly):
schema.statics.getLastWeek = function(name, cb) {
var keys = {} // can't remember what this is for
var condition = {} // maybe restrict to last 7 days
var initial = {day1:[],day2:[],day3:[],day4:[],day5:[],day6:[],day7:[]}
var reduce = function(obj, prev) {
// prev is basically the same as initial (except with whatever is added)
var day = obj.date.slice(0,-10) // figure out day, however it works
prev["day" + day].push(obj) // create grouped arrays
// you could also do something here to sort by _id
// which is probably also going to get you the latest for that day
// and use it to replace the last item in the prev["day" + 1] array if
// it's > that the previous _id, which could simplify things later
}
this.collection.group(keys, condition, initial, reduce, function(err, results) {
// console.log(results)
var days = results // it may be a property, can't remember
var lastDays = {}
days.forEach(function(day) {
// sort each day array and grab last element
lastDays[day] = days[day].sort(function(a, b) {
return a.date - b.date // check sort syntax, you may need a diff sort function if it's a string
}).slice(-1) // i think that will give you the last one
})
cb(lastDays) // your stuff
})
}
Some more comparisons between groups and map reduce from my blog:
http://j-query.blogspot.com/2011/06/mongodb-performance-group-vs-find-vs.html
There are no docs about the group command in the native driver, so you'll have to peer through the source code here:
https://github.com/christkv/node-mongodb-native/blob/master/lib/mongodb/collection.js
Also for sort, check check https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/sort for exact syntax
Edit: Better Idea!!!
Just have a special collection called "lastRequestOfDay" and make the _id the day.
Overwrite the value with each new request. It will be super easy to query and fast to write and will always have the last value written each day!

Add another property to the schema named dateAdded or something.
schema.statics.getLastWeek = function(name, fn) {
var oneday = 60 * 60 * 24
, now = Date.now()
, docs = []
for (var i = 0; i < 7; i++) {
this.where('name', new RegExp(name, 'i'))
.where('createdAt')
.lt(now - (i * oneday))
.gte(now - ((i + 1) * oneday))
.desc('createdAt')
.findOne(function(err,doc){
// might not always find one
docs.push(doc)
})
}
return fn(null, docs)
}

Try something like this:
schema.statics.getLastWeek = function(name, fn) {
var oneday = 60 * 60 * 24
, now = Date.now()
, docs = []
, that = this
function getDay(day){
that.where('name', new RegExp(name, 'i'))
.where('createdAt')
.gte(now - (day * oneday))
.desc('createdAt')
.findOne(function(err,doc){
docs.push(doc)
})
}
for (var i = 1; i <= 7; i++) {
getDay(i);
}
}

Nobody seems to be trying for "close to midnight". :) The issue I saw with the original code was that it checked for a time greater than or equal to x days ago... which will always return the most recent time. I'm confused as to why DeaDEnD's solution returns the same record 7 times, though. Also, you never called fn, but that's not really the biggest of your concerns, is it?
Try adding on .lt(now - (now % oneday) - (i - 1) * oneday) (assuming 0-indexed; if it's 1-indexed, change that to say i - 2)

Related

InfluxDB 2.0: Group Periods and Sum Up Duration

I have an InfluxDB (version 2), where an entry is written every second into my bucket, together with an identifier (uuid of the source) and a side value (some domain-specific measurement from 1 to 6). Instead of having a long list of such by-second logs:
2020-05-18T15:57:18 side=1
2020-05-18T15:57:19 side=1
2020-05-18T15:57:20 side=3
2020-05-18T15:57:21 side=3
2020-05-18T15:57:22 side=3
2020-05-18T15:57:23 side=2
2020-05-18T15:57:24 side=2
I'd like to condense those entries, so that I can calculate the duration, for how long side=x held true:
from 2020-05-18T15:57:18 to 2020-05-18T15:57:19 side=1 duration=2s
from 2020-05-18T15:57:20 to 2020-05-18T15:57:22 side=3 duration=3s
from 2020-05-18T15:57:23 to 2020-05-18T15:57:24 side=2 duration=2s
I also restrict the time period by a from/to range. This is my current query:
from(bucket: "mybucket")
|>range(start:2020-01-01T00:00:00.000Z, stop:2020-12-31T00:00:00.000Z
|>filter(fn:(r) => r.identifier == "3c583530-0152-4ed1-b15f-5bb0747e771e")
My approach is to read the raw data, and then iterate over it, detect changes of the side (something like current.side != last.side), and then report that as a new entry to my logbook. This approach is very inefficient, of course (JavaScript):
const data = fetchFromInfluxDB(from, to):
const terminator = { 'time': new Date(), 'identifier': '', 'side': -1 };
data.push(terminator); // make sure last item is also reported
const logbook = new Array();
let lastSide = -1;
let from = undefined;
for (let e of data) {
if (e.side != lastSide) {
if (from != undefined) {
let to = e.time;
let diff = Math.floor((new Date(to) - new Date(from)) / 1000);
if (diff > 0) {
logbook.push({'from': from, 'to': to, 'side': lastSide, 'seconds': diff});
}
}
lastSide = e.side;
from = e.time;
}
}
Is there a way to group and sum up that data using the InfluxDB query language?

Combine array of dates sorted in ascending order into array of date ranges

I have one array of dates, I want to create object containing start and end by checking continue dates.
EX.
dateArray = [
"2020-01-22T00:00:00.000Z",
"2020-01-23T00:00:00.000Z",
"2020-01-28T00:00:00.000Z",
"2020-01-29T00:00:00.000Z",
"2020-01-30T00:00:00.000Z",
"2020-01-31T00:00:00.000Z",
"2020-02-01T00:00:00.000Z",
"2020-02-02T00:00:00.000Z",
"2020-02-03T00:00:00.000Z",
"2020-02-04T00:00:00.000Z",
"2020-02-05T00:00:00.000Z",
"2020-02-06T00:00:00.000Z",
"2020-02-07T00:00:00.000Z",
"2020-02-16T00:00:00.000Z",
"2020-02-17T00:00:00.000Z",
"2020-02-18T00:00:00.000Z",
"2020-02-19T00:00:00.000Z",
"2020-02-20T00:00:00.000Z"
]
myRequirement = [{
start: "2020-01-22T00:00:00.000Z",
end: "2020-01-23T00:00:00.000Z"
},
{
start: "2020-01-28T00:00:00.000Z",
end: "2020-02-07T00:00:00.000Z"
},
{
start: "2020-02-16T00:00:00.000Z",
end: "2020-02-20T00:00:00.000Z"
}
]
I want to do this using in node.js.
I tried this using some nested for loops.
First i am running loop on main dateArray, Then checking is it first date or not, If it is first date then storing it as first objects start date, Then in next date case checking is it next most date of previous date or not.
let gapArray = [];
let startEndObj = {};
let tempStartDate;
let tempEndDate;
let tempNextDate;
await asyncForEach(finalAvailablityDatesArrayOFi.availeblityDatesArray, async (availeblityDatesArrayOFi) => {
console.log("availeblityDatesArrayOFi", availeblityDatesArrayOFi);
if (!tempStartDate) {
console.log("In if");
startEndObj.startDate = availeblityDatesArrayOFi;
tempStartDate = availeblityDatesArrayOFi;
let oneDatePlus = new Date(availeblityDatesArrayOFi).setDate(new Date(availeblityDatesArrayOFi).getDate() + 1);
tempNextDate = new Date(oneDatePlus);
console.log("startEndObj", startEndObj);
}
else if (tempStartDate) {
console.log("in else");
if (new Date(availeblityDatesArrayOFi).getTime() == new Date(tempNextDate).getTime()) {
console.log("Do nothing!");
tempStartDate = availeblityDatesArrayOFi;
tempEndDate = availeblityDatesArrayOFi;
let oneDatePlus = new Date(availeblityDatesArrayOFi).setDate(new Date(availeblityDatesArrayOFi).getDate() + 1);
tempNextDate = new Date(oneDatePlus);
}
else {
startEndObj.endDate = new Date(tempEndDate);
gapArray.push(startEndObj);
tempStartDate = '';
tempEndDate = '';
startEndObj = {};
}
}
});
Thank you!
Looks like a job for Array.prototype.reduce().
Note: hereafter assumption is made that few prerequisites are met:
source array items are valid ISO-formatted date strings or others, parseable by new Date() constructor, otherwise should be brought to one of supported format
source array items are sorted in ascending order, otherwise Array.prototype.sort() method must be applied in advance
array items do not include time of the day part (or this part is exactly the same for all items), otherwise consecutive date records may happen to have difference greater than 864e5 milliseconds (1 day) and more complex comparison is required
You may walk through your array and compare current items with previous/following, once you have a gap greater than 1 day you push new range into resulting array or modify end date for the last one:
const src = ["2020-01-22T00:00:00.000Z","2020-01-23T00:00:00.000Z","2020-01-28T00:00:00.000Z","2020-01-29T00:00:00.000Z","2020-01-30T00:00:00.000Z","2020-01-31T00:00:00.000Z","2020-02-01T00:00:00.000Z","2020-02-02T00:00:00.000Z","2020-02-03T00:00:00.000Z","2020-02-04T00:00:00.000Z","2020-02-05T00:00:00.000Z","2020-02-06T00:00:00.000Z","2020-02-07T00:00:00.000Z","2020-02-16T00:00:00.000Z","2020-02-17T00:00:00.000Z","2020-02-18T00:00:00.000Z","2020-02-19T00:00:00.000Z","2020-02-20T00:00:00.000Z"],
ranges = src.reduce((res,date,idx,self) => {
const rangeStart = !idx || new Date(date) - new Date(self[idx-1]) > 864e5,
rangeEnd = idx == self.length-1 || new Date(self[idx+1]) - new Date(date) > 864e5
if(rangeStart) res.push({startdate:date,enddate:date})
else if(rangeEnd) res[res.length-1]['enddate'] = date
return res
}, [])
console.log(ranges)
.as-console-wrapper {min-height:100%}
You need to be careful with this type of processing to determine all the business rules exactly. If the time component is not to be considered, then it should be removed, otherwise when comparing say 2020-01-01T00:00:00 to 2020-01-02T012:00:00 you will get a difference greater than 1 day but might not want it to be treated as the start of a new range.
For that reason, the "days difference" logic should be in a separate function, which also makes it easier to change date libraries if you're using one. The days difference is also signed, so make sure they are passed in the right order.
Otherwise, the following is pretty much the same as Yevgen's answer but a little more efficient I think as it only creates two Dates on each iteration instead of four.
let dateArray = [
"2020-01-22T00:00:00.000Z",
"2020-01-23T00:00:00.000Z",
"2020-01-28T00:00:00.000Z",
"2020-01-29T00:00:00.000Z",
"2020-01-30T00:00:00.000Z",
"2020-01-31T00:00:00.000Z",
"2020-02-01T00:00:00.000Z",
"2020-02-02T00:00:00.000Z",
"2020-02-03T00:00:00.000Z",
"2020-02-04T00:00:00.000Z",
"2020-02-05T00:00:00.000Z",
"2020-02-06T00:00:00.000Z",
"2020-02-07T00:00:00.000Z",
"2020-02-16T00:00:00.000Z",
"2020-02-17T00:00:00.000Z",
"2020-02-18T00:00:00.000Z",
"2020-02-19T00:00:00.000Z",
"2020-02-20T00:00:00.000Z"
];
// Simple difference in days function
function daysDiff(d0, d1) {
return Math.round((d1 - d0) / 8.64e7);
}
let ranges = dateArray.reduce((acc, curr, i, arr) => {
// If first date, initialise first object
if (!acc.length) {
acc.push({start: curr, end: curr});
} else {
let d0 = new Date(curr);
let d1 = new Date(arr[i-1]);
// If difference greater than 1 day, end previous range
// and start a new range
if (daysDiff(d1, d0) > 1) {
acc[acc.length - 1].end = arr[i-1];
acc.push({start: curr, end: curr});
}
}
return acc;
}, []);
console.log(ranges);

comparing two arrays for intersecting values

I'm trying to use JavaScript to compare 2 different arrays and test for intersecting values.
This array contains ranges of times of availability for a 7 day week. In the availability array below each key represents a day of the week starting with Sunday. So key 0 = Sunday, key 1 = Monday..... maximum number of keys would be 6 which = Saturday
var availability = [["8:30AM-12PM","2PM-6PM"],
["6:15AM-9:30AM","1PM-4PM","8PM-11:15PM"],[],["9AM-9PM"]];
The below array need1 contains ranges of times of need for specific days throughout the week (anywhere from Sunday{key0} to Saturday{key6}). It uses the same key format as the above availability array. need1 array should match within the times and days listed in the availability array. So when comparing need1 to availability a match should be found.
var need1 = [["9AM-11:30AM","3PM-5PM"],[],[],["2PM-6:30PM"]]; //matches
The below array need2 is an example of an non-match, since the times of need ranges are outside the ranges of times and days listed in the availability array. So when comparing need2 to availability NO match should be found.
var need2 = [["7:30AM-11:30AM"],[],[],["2PM-6:30PM", "8PM-10:30PM"]]; //does not match
I'm trying to figure out how to compare these 2 arrays to match up the need ranges with the availability ranges. Meaning the need ranges have to completely fit inside the availability ranges for each day. All I'm looking for is a simple true or false returned value when comparing. true = match and false = NOT a match. However, I have no idea how to to efficiently do this. Any help would be appreciated!
Also, If need be I can lay out the array values in a different format if it would make comparing them easier. i.e. using date values instead of strings, or 24 hour format instead of 12 hour format
I'm going to take a risk here and take a slightly different approach than you've started with, but which provides a solution to your basic question: are there any matches between the available times and the needed times?
Before I present code, here are some recommendations:
1. Use an Object at the top level, not an array. Using array positions as meaningful is dangerous. Instead utilize the power of JavaScript object literals.
2. Separate your start and stop times, do not put them in the same string.
3. Utilize the power of native Array methods.
I make these recommendations and provide the following code snippet as it seems that you have some wiggle room in how you approach the problem.
UPDATED
Changed assumption per request. Only returns match for a given day, if every needed start/time slot finds a matched time slot in the availability object.
Something like the following should get you where you want to go. This will return an object of the matched needs.
/* structure your schedule as objects with arrays of objects of start/stop times */
const availability1 = {
sunday: [
{
start: '08:30',
stop: '12:00'
},
{
start: '14:00',
stop: '18:00'
}
],
monday: [{
start: '06:25',
stop: '11:45'
}],
wednesday: []
};
const need1 = {
// will be matched, every needed time slot is within an availability slot
// on the same day
sunday: [
{
start: '09:45', // has a match
stop: '12:00'
},
{
start: '14:00', // has a match
stop: '18:00'
}
],
monday: [ // will not be matched because...
{
start: '14:00', // has NO match
stop: '16:00'
},
{
start: '07:00', // has a match
stop: '10:00'
}
],
tuesday: []
};
const getMinutes = (timeString) => {
const timeParts = timeString.split(':');
const hours = Number(timeParts[0]);
const minutes = Number(timeParts[1]);
const timeInMinutes = (hours * 60) + minutes;
// console.log(`timeInMinutes: ${timeInMinutes}`);
return timeInMinutes;
}
const isTimeMatch = (availabilityTime, needTime) => {
const availStart = getMinutes(availabilityTime.start);
const availStop = getMinutes(availabilityTime.stop);
const needStart = getMinutes(needTime.start);
const needStop = getMinutes(needTime.stop);
console.log(`Availibility ${availabilityTime.start} (${availStart}) - ${availabilityTime.stop} (${availStop})`)
console.log(`Need ${needTime.start} (${needStart}) - ${needTime.stop} (${needStop})`)
const startTimeMatch = availStart <= needStart;
const stopTimeMatch = availStop >= needStop;
const isMatch = startTimeMatch && stopTimeMatch;
console.log(`is match: ${isMatch}`);
return isMatch;
};
const compareDays = (availTimes, needTimes) => {
return needTimes.map((needTime, i) => {
const matches = availTimes.filter((availTime) => {
return (isTimeMatch(availTime, needTime));
});
needTime.match = matches.length > 0;
return needTime;
}).filter((needTime, i, allNeedTimes) => {
return (allNeedTimes.every((i) => i.match === true));
});
}
function findMatches(availability, need) {
const matches = Object.keys(availability).reduce((accumulator, day) => {
if (availability[day] && need[day]) {
console.log(`Possible matches found on ${day}`)
const matches = compareDays(availability[day], need[day]);
if (matches.length > 0) {
accumulator[day] = matches;
}
}
return accumulator;
}, {});
return (Object.keys(matches).length === 0) ?
false : matches;
}
const matchedTimes = findMatches(availability1, need1);
if (matchedTimes) {
console.log('The following needs match availability:');
console.log(matchedTimes);
} else {
console.log('No matches found');
}

How to ask an API for many values (of the past 14 days) via iterative timestamp manipulation?

I want to calculate the RSI - (Relative Strength Index)(Last 14 Days) for the Bitcoin-Price. The necessary data for the past 14 days comes from an API. The result should be stored in a variable for further processing. I tried different methods, but the result wasn´t working. I think i don´t found the right way to solve this. I was not able to create a complete and working result, so I am here to ask my first question on Stack Overflow.
How can I ask the API for the course of the past 14 days via
iterative timestamp manipulation?
Timestamp now -1day/-2days.... (&ts=xxxxxxxxxxxx) - example: (ts=1452680400)
https://min-api.cryptocompare.com/data/pricehistorical?fsym=BTC&tsyms=USD&ts=1452680400
How can i put the values from the API in an array?:
var closePrices= {
var : 'text',
array: [BTCDay1, BTCDay2, BTCDay3, BTCDay4, BTCDay5, BTCDay6, BTCDay7, BTCDay8, BTCDay9, BTCDay10, BTCDay11, BTCDay12, BTCDay13, BTCDay14]
};
Then I want to put the array in this calculation formular:
public static double CalculateRsi(IEnumerable<double> closePrices)
{
var prices = closePrices as double[] ?? closePrices.ToArray();
double sumGain = 0;
double sumLoss = 0;
for (int i = 1; i < prices.Length; i++)
{
var difference = prices[i] - prices[i - 1];
if (difference >= 0)
{
sumGain += difference;
}
else
{
sumLoss -= difference;
}
}
if (sumGain == 0) return 0;
if (Math.Abs(sumLoss) < Tolerance) return 100;
var relativeStrength = sumGain / sumLoss;
return 100.0 - (100.0 / (1 + relativeStrength));
}
Several quite broad questions (it usually works better if you post some of the code you already tried to write yourself)... But fun ones to solve.
Assuming we can use es6 syntax, Promises and fetch (if you can't, look up how to polyfill & transpile).
Creating an array of timestamps
To get a timestamp for the current date, you write Date.now(). To change this time stamp to a day n days ago, we decrease it by the number of milliseconds in a day:
const timeStampForDaysAgo =
nrOfDays => Date.now() - 1000 * 60 * 60 * 24 * nrOfDays;
// e.g.: yesterday
const yesterday = timeStampForDaysAgo(1);
Now, if we fill an array of the integers 0...14, we can use map to create an array of timestamps!
const lastTwoWeeks = Array.from(Array(14), (_, i) => timeStampForDaysAgo(i))
Doing the requests
In modern browsers, you can use fetch to do requests. We'll need a list of URLs though, not just timestamps. To make the URLs, we again use map:
const urls = lastTwoWeeks.map(ts => `https://your-url.com?ts=${ts}`);
Now that we have URLs, we can create our requests (again, using map):
const btcRequests = urls.map(url => fetch(url).then(r => r.json()));
Calculating the result
We can't start calculating the result until all requests have finished. That's where Promise.all comes in:
Promise.all(btcRequests).then(calcRSI);
This makes sure we only call calcRSI until all requests have finished.
Because the API returns objects of { BTC: { USD: Number } }, we'll have to extract the numbers before we can do our math.
Promise
.all(btcRequests)
.then(responses => responses.map(obj => obj.BTC.USD))
Now that we have an array of numbers, we can finally call the calculate function you gave in C# code. Of course, you'll have to translate it to javascript first.
const calcRSI = (arrayOfValues) => /* do math, return value */
Promise
.all(btcRequests)
.then(responses => responses.map(obj => obj.BTC.USD))
.then(calcRSI)
.then(rsi => console.log("The RSI for the last 14 days, is:", rsi);
See the code in action in this fiddle (make sure to open the console)

How do I loop through objects and categorize by timestamps in Javascript?

I have an array of objects that have a keys called timestamp and motion. motion contains a value and timestamp contains a unix timestamp. I want to iterate over a number of the objects and find what "time of day" period they correspond to, I then want to total up the motion values for that given time of day and save the entire thing in an array of arrays. I want the duration to be changeable.
Let's say these are my objects;
{
timestamp: 1397160634,
motion: 2,
id: '534771d8c311731e21c75c9f'
},
{
timestamp: 1397160634,
motion: 3,
id: '534771d8c311731e21c75c9f'
}
Now I create my results array
var sampleDuration = 60; // Min
var minutesInDay = 1440;
var samplesPerDay = minutesInDay/sampleDuration;
var finalResultItem = []
for (var i = 0; i < samplesPerDay; i++) {
var IndividualresultArray = []
IndividualresultArray.push(60*i);
IndividualresultArray.push(0);
finalResultItem.push(IndividualresultArray);
}
I now have an array of arrays with each subarray's first item being a number (corresponding to a minute stamp) and the second value being zero.
I would now like to loop through all my objects and increment the second value (motion) based on the time of day range that is in the timestamp
_forEach(objects, function (object) {
{
// grab the timestamp
// figure out which minute range it coresponds to
// increment the array value that corresponds to the minute stamp
// rinse and repeat
}
this is where I go blank, I need the end result to look something like this
[[30, 5],[60, 20],[90, 5],[120, 0] .........]
or it could even look like this
[[000002400, 5],[000003000, 20],[000003600, 5],[000004200, 0] .........]
where the first value is a timestamp that ignores the year, month, and day, and only considers the time of day.
I have considered using moment.js in some capacity but I'm not sure how. Any help with this problem would be great.
I created a jsFiddle for you. The motion increment logic should look like (I'm using jQuery here but you get the point)
// Loop through and increment motion
$.each(objs, function (idx, obj) {
var date = new Date(obj.timestamp * 1000); // Convert to milliseconds
var minutesInDay = date.getUTCHours() * 60 + date.getUTCMinutes(); // Remove UTC for local time!
var minuteRange = Math.floor(minutesInDay / sampleDuration);
finalResultItem[minuteRange][1] += obj.motion;
});
EDIT: Removed some discussion after your edit. I also used more generic logic based on sampleDuration.
This should do it:
_forEach(objects, function (object) {
var date = new Date(objec.timestamp*1000);
var minuteOfDay = date.getUTCHours()*60+date.getUTCMinutes();
finalResultItem[minuteOfDay][1] += object.motion;
})
For a variable sample rate, employ a secondOfDay and divide that by your sampleDuration, then floor it to get your array index.

Categories