forEach unexpected token adding new property to existing array - javascript

I want to add a new proeprrty call total_days calculate using date_from and date_to but my forEach got an expected token error.
let applicants = [{
date_from: '2017-05-05',
date_to: '2017-05-10'
},{
date_from: '2017-05-08',
date_to: '2017-05-12'
}]
calculateDays = applicants.forEach(obj =>
applicants['total_days'] = (obj.date_from).diff(obj.date_to, 'days')+1;
)
No clue what's wrong here.

You didn't exactly clarify what you wanted but I tried to take a guess by your code.
My guess is that you wanted to create a new array of applicants from the old array of applicants but in the new array, you wanted to add a property to each object in that array that is the difference in days of the two dates.
To do so, you can use Array.prototype.map to map each item from your array to a new array.
I'm also using Object.assign to clone each object so that the original array is unmodified.
I'm also parsing the date strings into number. The parsed number is the number of milliseconds elapsed since 1 January 1970 00:00:00 UTC. If I take the difference of the two numbers and divide that be the millisecondsInADay then I'll get how many days elapsed in between.
The result is then stored into a new array calculateDays.
Let me know if you need more clarification.
let applicants = [{
date_from: '2017-05-05',
date_to: '2017-05-10'
}, {
date_from: '2017-05-08',
date_to: '2017-05-12'
}]
const millisecondsInADay = 1000 * 60 * 60 * 24;
const calculateDays = applicants.map(obj => Object.assign({}, obj, {
total_days: ((
Date.parse(obj.date_to) - Date.parse(obj.date_from)
) / millisecondsInADay) + ' days'
}));
console.log(calculateDays);

Assuming you want to add a new property to all objects, you could use obj as variable with a new property.
applicants.forEach(obj => obj.total_days = obj.date_from.diff(obj.date_to, 'days') + 1);
// ^^^

Related

I want to get a list of item from mongodb that is less than or equal filtered by the field created

This is my code:
const creationDateOfSentence = new Date( parseInt(bookId.substring(0,8), 16 ) * 1000 );
const allOlderVerses = await Book
.find({
bookId: bookId,
created: {$lte: creationDateOfSentence}
});
bookId is a string id of an _id.
I always get an array who is of size 0. Do you know what I am doing wrong? I just want to get items that are older or equal in creation date of this item id: bookId.
Thanks.

How can I target a deeply nested object in google realtime database?

I want to make a cron job that deletes deeply nested objects in my realtime database that are older than 24 hours.
I have looped through and reached the deeply nested object, but I can't grab/target the value of "addedTime" in the object. How do I grab that value so I can run .remove on the parent? So far, it comes back as undefined or it throws an error.
.schedule("every 1 hours")
.onRun(context => {
const rootDatabaseRef = admin.database().ref("ghostData/");
return rootDatabaseRef.ref.once("value").then(function(snapshot) {
console.log("snap", snapshot.val());
snapshot.forEach(function(userSnapshot) {
let buckets = userSnapshot.val().buckets;
console.log("buckets", buckets);
buckets.forEach(function(bucket) {
let currentTimeYesterday = new Date(
new Date().getTime() - 24 * 60 * 60 * 1000
).getTime();
let addedTime = bucket.val().addedTime;
console.log("curr time", currentTimeYesterday);
console.log("addedTime", addedTime);
});
});
Here is the data in my realtime database as well as the logs from the serverless cloud functions:
I think you're having problems with looping, because when you do this "buckets.forEach(function(bucket)" --> bucket in your case is the first element of the list ,
and every element has a nested dictionary , so first you have to iterate the dictionary and for each key in the dictionary , you'll get another dictionary , and you've to grab
only the added-time value.
I know it's difficult to understand but I think it's happening because you're not looping correctly.
Try the code below or something similar.
buckets.forEach(function(bucket){
let currentTimeYesterday = new ......
bucket.forEach(function(dict){
Object.keys(dict).forEach(k => {
console.log(k, ':', dict[k].addedTime);
let addedTime = dict[k].addedTime;
});
....
}
....
}

Trying to understand map in Javascript with moment library timestamps

I have following code to get list of object with new timestamp. I am using momemt lib to update time. Basic logic is to loop N times and collect list of times adding 1 min to each.
var moment = require('moment');
var _ = require('lodash');
var startDate = moment("1995-12-25");
var currentDate = startDate;
var result = _.range(5).map(function () {
const nextTimestamp = currentDate.add(60, 's');
console.log('nextTimestamp: ' + JSON.stringify(nextTimestamp));
currentDate = nextTimestamp;
return {
timestamp: nextTimestamp
}
});
console.log('result: ' + JSON.stringify(result, null, 2));
I am expecting it will give a array on timestamp with 1 min difference. The output I am seeing is:
nextTimestamp: "1995-12-25T06:01:00.000Z"
nextTimestamp: "1995-12-25T06:02:00.000Z"
nextTimestamp: "1995-12-25T06:03:00.000Z"
nextTimestamp: "1995-12-25T06:04:00.000Z"
nextTimestamp: "1995-12-25T06:05:00.000Z"
result: [
{
"timestamp": "1995-12-25T06:05:00.000Z"
},
{
"timestamp": "1995-12-25T06:05:00.000Z"
},
{
"timestamp": "1995-12-25T06:05:00.000Z"
},
{
"timestamp": "1995-12-25T06:05:00.000Z"
},
{
"timestamp": "1995-12-25T06:05:00.000Z"
}
]
Can anyone help me understand why array is coming with last timestamp for all array element.
Thanks.
This happens because you work with one currentDate object, which you keep mutating. Even when you have put that object in the array, it does not stop from getting mutated by what you do in the next iteration.
You need to create separate objects, and for this you can use the clone method available in momentjs:
currentDate = nextTimestamp.clone();
Or alternatively, call moment():
currentDate = moment(nextTimestamp);
Your problem has nothing to do with map.
See the documentation for moment:
It should be noted that moments are mutable. Calling any of the manipulation methods will change the original moment.
Each entry in the array is a reference to the same moment, which you just modify the value of repeatedly.
You need to use a new moment object (you can get one by clone()ing the old one) each time you add the time to it:
var startDate = moment("1995-12-25");
var nextTimestamp = startDate;
var result = _.range(5).map(function () {
nextTimestamp = nextTimestamp.clone().add(60, 's');
console.log('nextTimestamp: ' + JSON.stringify(nextTimestamp));
return {
timestamp: nextTimestamp
}
});
The Array.map function returns a new array with the results being equal to the given function being applied to every element in the array. Also you are not getting any of the elements to change them. Map takes in a parameter for the current element that needs to be changed.
//I didn't use lodash but the theory is the same
var range = [0, 1, 2, 3, 4, 5];
var result = range.map(function (element) {
return element += 1;
});
console.log(result); //1, 2, 3, 4, 5, 6

add items into two arrays (future and past dates) based on date

I am trying to find a way to sort posts into two arrays: upcoming and current (upcoming posts are in the future and current have already been posted).
All posts have a scheduledPubDate that is a date string in the format YYYY-MM-DDT00:00:00. and todays date has to be a Date object as it will need to stay relevent (I am using moment())
Is it possible to compare these two different things without having to use a .split and compare the month / day /year separately
angular.forEach(data.items, function (key, index) {
if (moment(key.scheduledPubDate) > moment()) {
$scope.upcomingPosts.push(item[index]);
} else if (moment(key.scheduledPubDate) <= moment()) {
$scope.currentPosts.push(item[index]);
};
});
Presumably you want the string treated as UTC, a simple parser for that is:
// Expected format YYYY-MM-DDT00:00:00
function parseUTC(s) {
var b = s.split(/\D/);
return new Date(Date.UTC(b[0], b[1]-1, b[2], b[3], b[4], b[5]));
}
Note that this doesn't allow for invalid dates. If needed, an extra line if code is required. So now you can do:
if (parseUTC(key.scheduledPubDate) > new Date()) // or Date.now()
You really don't need moment.js for this.
JavaScript's built-in Date object will help you here.
var date = Date.parse('2014-01-21T12:45:13');
date < Date.now() // true
For the purpose of an example, let's assume items is an array of posts:
var items = [{
scheduledPubDate: '2014-01-21T12:45:13'
// ...other keys here
}, {
scheduledPubDate: '2017-03-01T15:21:00'
} // ...and so on
];
Then a reduce operation over items can categorize the posts:
var posts = items.reduce(function (memo, item) {
memo[Date.parse(item.scheduledPubDate) <= Date.now() ? 'current' : 'upcoming'].push(item);
return memo;
}, { current: [], upcoming: [] });
Now posts.current will contain an array of all posts from items whose scheduledPubDate is before the current date, and posts.upcoming will contain an array of all scheduled posts.
Edited to use Date.parse, to avoid unreliable behavior pointed out by RobG. This requires that all dates be in the YYYY-MM-DDT00:00:00 format you specified; if that is not the case, another solution will be required.
You have to specify the date format of the string
var format = "YYYY-MM-DDT00:00:00";
angular.forEach(data.items, function (key, index) {
if (moment(key.scheduledPubDate, format) > moment()) {
$scope.upcomingPosts.push(item[index]);
} else if (moment(key.scheduledPubDate, format) <= moment()) {
$scope.currentPosts.push(item[index]);
};
});
Working example (See the console.log): http://jsbin.com/fejaxiguce/1/edit?html,output
First create an array of elements, in any order, and then use the .sort() method.
http://www.w3schools.com/jsref/jsref_sort.asp
var points = [40, 100, 1, 5, 25, 10];
points.sort(function(a, b){return a-b});
Just substitute the above logic with your own. a and b above can be objects.

Pulling values from an array based on date?

I have an array of data points, [date, value], like so...
data_points = [[1310279340, 1], [1310279340, 1]]
I need to create an array based on "milliseconds ago", with ten values for each second, or a value for every 100ms going backwards.
The new array's values will look like, [ms ago, value], like so...
ms_ago_points = [[0,3],[100,6],[200,7]]
So the last value in that array represents [200ms ago, value of 7].
I'm having a hard time figuring out how to get "value from Xms ago" based on date values in the first array. If needed I might be able to get the initial date/values in a format other then an array if it would be easier to poll for data.
Thanks for any guidance!!
edit: I'm looking to repeat the same value between dates for every 100ms tick that lands between them.
var now = Date.now(),
l = data_points.length,
ms_ago_points = [];
for ( var c = 0; c < l; c++ ) {
ms_ago_points.push([now - data_points[c][0],data_points[c][1]);
}
Maybe you need to sort the ms_ago_points afterwards, but this should give you your desired array.
However: I'd seriously suggest you not to work with multi-dimesional arrays but objects instead:
ms_ago_points= [{ms: 0, value: 3},{ms:100, value: 6}...]
*edit: This of course assumes that your data_points are already in 100ms steps, otherwise you'd have to implement an interpolation :)
I believe this meets your requirements:
function msFromDataPoints(nowTime, dataPoints) {
var d = dataPoints.length,
i = 0,
anchor = Math.floor(nowTime.getTime() / 100) * 100,
ms = anchor,
msArr = [];
while (d--) {
while (ms >= data_points[d][0] * 1000) {
msArr.push([anchor - ms, dataPoints[d][1]];
ms -= 100;
}
}
return msArr;
}
See it in a Js Fiddle.
Note: I find the data structures to be a little strange. An object for the input seems best:
[{date: 1310279340, value: 1}, {date: 1310279340, value: 1}]
And your output array doesn't need the milliseconds at all, as simply [1, 1, 5, 5, 3, 2 4] (or whatever) would be understood to mean millisecond indexes starting at 0 and increasing by 100. If absolutely required, you could use a sparse array:
result = [];
result[0] = 1;
result[100] = 1;
result[200] = 5; // and so on

Categories