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);
// ^^^
I have defined a table for a portfolio's profit and loss. For each single day the P&L is shown in appropriate DC bar chart, but I want to add a cumulative sum that follows the column date. This should in the example return for End of September only the P&L slice for September, for October the slice for both September and October and so one. If any filter applies in the crossfilter, the applied cumulative sum should apply on filtered data.
*
Date,Cpty,internalRating,ratingSegment,externalRating,Sector,assetClass,riskFactor,riskBucket,sensi,marketMove,PL
30.09.16,DEF,2A,IND,AA,Industrials,IR,EUR,10,-1000,2,-2000
30.09.16,JKL,3B,SERV,BBB,Services,IR,USD,10,-1000,4,-4000
30.09.16,JKL,3B,SERV,BBB,Services,IR,JPY,10,-10000,6,-60000
30.09.16,JKL,3B,SERV,BBB,Services,CS,CDS_JKL,10,-4000,4,-16000
30.09.16,MNO,2B,TRAN,BB,Transportations,IR,EUR,10,1000,-4,-4000
30.09.16,MNO,2B,TRAN,BB,Transportations,CS,CDS_MNO,10,-1000,5,-5000
31.10.16,DEF,2A,IND,AA,Industrials,IR,EUR,10,-1500,6,-9000
31.10.16,JKL,3B,SERV,BBB,Services,IR,USD,10,1500,12,18000
31.10.16,JKL,3B,SERV,BBB,Services,IR,JPY,10,15000,18,270000
31.10.16,JKL,3B,SERV,BBB,Services,CS,CDS_JKL,10,6000,12,72000
31.10.16,MNO,2B,TRAN,BB,Transportations,IR,EUR,10,-1500,-12,18000
31.10.16,MNO,2B,TRAN,BB,Transportations,CS,CDS_MNO,10,1500,15,22500
30.11.16,DEF,2A,IND,AA,Industrials,IR,EUR,10,1428,6,8568
30.11.16,JKL,3B,SERV,BBB,Services,IR,USD,10,1085,12,13020
30.11.16,JKL,3B,SERV,BBB,Services,IR,JPY,10,5046,18,90828
30.11.16,JKL,3B,SERV,BBB,Services,CS,CDS_JKL,10,2579,12,30948
30.11.16,MNO,2B,TRAN,BB,Transportations,IR,EUR,10,-253,-12,3036
30.11.16,MNO,2B,TRAN,BB,Transportations,CS,CDS_MNO,10,409,15,6135
*
Any clue how I can proceed ? Do I need reductio for this ?
Thanks in advance !
As an alternative to #Ethan's clever answer, this is also a great opportunity for a "fake group" (and one of the first documented uses of that technique IIRC).
From the dc.js FAQ:
function accumulate_group(source_group) {
return {
all:function () {
var cumulate = 0;
return source_group.all().map(function(d) {
cumulate += d.value;
return {key:d.key, value:cumulate};
});
}
};
}
Use it like this:
data.forEach(function(r) {
r.Date = dateFormat.parse(r.Date);
});
var cf = crossfilter(data)
var dateDim = cf.dimension(function(d) { return d.Date; });
var plGroup = dateDim.sum(function(d) { return d.PL; });
var accumPLGroup = accumulate_group(plGroup);
If you are using Crossfilter 1.4.0-alpha.06, you can do this using an array dimension. Something like the following:
function getDates(d) {
// This function should return an array of dates or months from
// d.Date until the end of the year.
return [...]
}
var cf = crossfilter(data)
var runningSumDim = cf.dimension(getDates, true)
var runningSumGroup = runningSumDim.sum(function(d) { return d.PL; })
That should "just work" once you work out the logic to derive the array of subsequent months.
What does this do? The dimension accessor should return an array. This array is assumed to be the list of group values that this record should be included in. So you would want the array to include the current month key and the month keys of all subsequent months the record should be included in. Note, this should be an array of subsequent months, not previous months. Somewhat counter-intuitive, but think of it as the answer to the question "What months should this value be counted in?".
I have an array of objects with a date formatted in MMMM Do YYYY format. I need to convert this into a UNIX timestamp to arrange them and then convert them back into the readable date format.
However, in doing this. It seems that my changes from within the forEach callback are not applied to the $scope.lalala variable.
My code:
function compare(a, b) {
if (a.date < b.date)
return -1;
if (a.date > b.date)
return 1;
return 0;
}
$scope.lalala = arrayofincompleteorders;
$scope.lalala.forEach(function(hiVanilla, index) {
hiVanilla.date = moment(hiVanilla.date, 'MMMM Do YYYY').format('x');
if (index == $scope.lalala.length - 1) {
$scope.lalala.sort(compare); timestamps as expected
console.log($scope.lalala); //logs the date property with unix
callback();
}
});
console.log($scope.lalala); //logs the date property with unix timestamps, why?
function callback() {
$scope.lalala.forEach(function(order, index) {
console.log(order.date); //unix timestamp
$scope.lalala[index].date = moment(order.date, 'x').format('MMMM Do YYYY');
console.log($scope.lalala[index].date); //formatted timestamp
});
};
Edit: I have the same problem even with the angular.forEach loop in the callback:
function callback(){
angular.forEach($scope.lalala, function(value, key) {
console.log(value.date);
value.date = moment(value.date, 'x').format('MMMM Do YYYY');
console.log($scope.lalala[key].date);
});
console.log("fire!");
$scope.apply();
};
I get the dates to change successfully but then it says that $scope.apply() is not a function which borks the rest of my script.
Edit2:
I got rid of the callback and have everything in one angular.forEach but it still doesn't apply?
$scope.lalala = arrayofincompleteorders;
angular.forEach($scope.lalala, function(hiVanilla, key) {
hiVanilla.date = moment(hiVanilla.date, 'MMMM Do YYYY').format('x');
if (key == $scope.lalala.length - 1) {
$scope.lalala.sort(compare); //timestamps as expected
console.log($scope.lalala); //logs the date property with unix
console.log(hiVanilla.date); //unix timestamp
hiVanilla.date = moment(hiVanilla.date, 'x').format('MMMM Do YYYY');
console.log($scope.lalala[key].date); //formatted timestamp
}
});
console.log($scope.lalala); //logs the date property with unix timestamps, why?
It looks like I was using angular.forEach in a way that it was not designed.
The following worked, basically I just assigned it by pushing it into an empty array rather than trying to alter the array from which I was looping inside of:
$scope.lalala=[];
var log = = arrayofincompleteorders;
angular.forEach(log, function(value, key) {
if(value.complete!="TRUE")
{
i++;
value.date = moment(value.date, 'x').format('MMMM Do YYYY');
this.push(value); //put the new value in $scope.lalala as specified below
}
}, $scope.lalala);
I want all Date types in my entities to always be converted to momentjs. The solution (Code 2) I used for this works fine for getResources (Code 1), the initializer is triggered for both the 'Event and 'Shift' entities. But when I call getUser the expand works as it should and I get the right data for both 'Order' and 'Event', but the initializer for 'Event' never triggers. Any ideas why? Is it because I'm using a property path expand?
Also, if you can think of a better solution to convert all Date types in my entities to momentjs I will gladly accept that too.
Code 1:
var getResources = function () {
var query = breeze.EntityQuery
.from("Resources")
.expand("Event, Shift")
.orderBy("ResourceId");
return manager.executeQuery(query)
.fail(fail);
}
var getUser = function () {
var query = breeze.EntityQuery
.from("LoggedInUser")
.expand("Order.Event")
.orderBy("Email");
return manager.executeQuery(query)
.fail(fail);
}
Code 2:
function configureMetadataStore(metadataStore) {
metadataStore.registerEntityTypeCtor('Shift', null, momentInitializer);
metadataStore.registerEntityTypeCtor('Event', null, momentInitializer);
metadataStore.registerEntityTypeCtor('Order', null, momentInitializer);
}
function momentInitializer(entity) {
var newMoment,
prop;
for (prop in entity) {
if (ko.isObservable(entity[prop])) {
if (entity[prop]() instanceof Date) {
newMoment = ko.observable(moment(entity[prop]()));
entity[prop] = newMoment;
}
}
}
}
I am sure there is a better and more detailed answer for this, but from what I understand you are probably trying to display the date in a given format, not actually convert it in the database, correct?
If you are using a binding handler such as Knockout.js you can just change the format in which it is displayed instead of converting the date/time stamp. I am always cautious of converting the dates just to display them because I have had issue in the past with the database getting mad at me for such a thing.
Here is an example of a custom binding handler to show date time as May 29th, 2013, 2:22:00 pm
ko.bindingHandlers.DateTime = {
update: function (element, valueAccessor) {
var value = valueAccessor();
var date = moment(value());
var strDate = date.format('MMMM Do YYYY, h:mm:ss a');
$(element).text(strDate);
}
};