How to get previous Six months into an array - javascript

I am trying to use moment to get the previous six months, using the below code.
ngOnInit(){
let mom: moment.Moment;
var d = new Date();
let numberOfMonths=6;
let previousSIxMonths:string[]=[];
while (this.numberOfMonths > 0) {
this.previousSixMonths.push(mom.subtract(this.numberOfMonths, 'months').format('MMMM'));
this.numberOfMonths--;
console.log(this.numberOfMonths);
}
console.log(this.previousSixMonths);
}
However these cards should be displayed whenever I am on the page, and hence I have written the above code inside OnInit. Once I have all the past six months in the array, the idea is to loop over the array and display in cards. But the doesn't really work for me.
I want all my previous six months to be in an array so that I could loop across the array.
Considering this is October month, the expected output should be:
["Oct","Sept","Aug","July","June","May"]

Here is a quick way to do what you're needing:
var previousSixMonths = function(){
let n = 0;
let arRet = [];
for(; n < 6; n++)
arRet.push(moment().subtract(n, 'months').format('MMMM'));
return(arRet)
}();
console.log(previousSixMonths);

Related

printing array shows different values when printing only the last element - javascript

im getting logs with a date property in the ISO YYYYMMDDhhmmss format, and im transfering them to Date object using the map function as seen below.
when I print the whole object I get the wrong dates but when I print just one element of the array its correct, this is bizarre to me,what am I missing ?
let dates = ascendingLogs.map(log => new Date(log['date'].replace(
/^(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/,
'$4:$5:$6 $2/$3/$1'
)));
console.log(dates[dates.length - 1])
console.log(dates)
let numberOfElements = 8
let timeGap = (dates[dates.length -1].getTime() - dates[0].getTime()) / numberOfElements;
let labels = []
for (let i = 1; i < numberOfElements; i ++){
dates[i] = new Date(dates[i - 1].getTime() + (timeGap));
};
below are the console.log of 1. last element in dates, whole dates array, ascendingLogs object
EDIT :
I have been able to narrow down the problem to the for loop, what im thinking is that it somehow asynchronously changes the console.log value but I dont know how to solve it.
heres a reproducible example you could examine :

How to sort elements of array in natural order with mixed (letters and numbers) elements

i am trying to create google-form which is used to register students agreements on practice. Every agreement is registered and got agreement number which format is Last to digits of current year-T-number of agreement at this year/M. For example for now it is 17-T-11/M. The number of agreement currently is written by person which is responsible for practice.
Here is code of script below:
function onChange(e)
{
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[1];
var range = sheet.getDataRange();
var values = range.getValues();
var comboValues = ['16-T-105/M'];
// removing titles from 0 column and 1 line (titles)
for (var i = 1; i <= values.length; i++) {
var v = values[i] && values[i][0];
v && comboValues.push(v)
}
// Sort the values
comboValues.sort(
function(a, b) {
if (b.toLowerCase() < a.toLowerCase()) return -1;
if (b.toLowerCase() > a.toLowerCase()) return 1;
return 0;
}
);
Logger.log(comboValues);
// google-form modification
var form = FormApp.openById('1SHgVIosoE34m9cny9EQySljvgnRpzffdFEZe-kzNOzA');
var items = form.getItems();
for (i = 4; i < items.length; i++) {
Logger.log("ID: " + items[i].getId(), ': ' + items[i].getType());
}
form.getItemById('2087613006').asListItem().setChoiceValues(comboValues);
I got issue which is related with lexicographical order. Person which register agreement choose from list last registered agreement number: i tryed to do that last registered agreement number will always be at list top. As time when i started this everything was fine (it started with number 16-T-105/M), but new year come and soon after 17-T-10/M agreement was registered i got issue, that 17-T-10/M was not on list top. Soon i realised that this happens because script use lexicographical order and "thinks" that 2 is more than 10. So i understood that i somehow will have to change that order and do that 2 is less than 10, 11 is less than 101 and so on.
My question is how to do that? I guess that i need to sort array elements in natural order - but i do not have idea how to do this.
I tryed to google how to do it , but result was not satisfactory - maybe my knowledge of coding is pretty limited (i am PhD student of Psychology, not Informatics) :)
Maybe someone will help how to solve that problem.
Updates:
Link to spreadsheet: https://docs.google.com/spreadsheets/d/1FH5qYTrLUNI2SCrcaqlwgu8lzAylaTkZsiALg0zIpCM/edit#gid=1620956794
Link to google-form (Copy of actual form): https://docs.google.com/forms/d/e/1FAIpQLSerJfkv1dgHexUwxppXNyhb46twOZgvEMOIVXSOJoED3SLmyQ/viewform
You should adjust the sorting method to account of the peculiarities of the data. Here is one way to do this: the function splitConvert processes each string, splitting it by non-word characters and then converting what can be converted to integers (and lowercasing the rest). Then the comparison goes through this array one by one.
comboValues.sort(
function(a, b) {
var as = splitConvert(a);
var bs = splitConvert(b);
for (var i = 0; i < as.length; i++) {
if (bs[i] < as[i]) return -1;
if (bs[i] > as[i]) return 1;
}
return 0;
}
);
function splitConvert(str) {
return str.split(/\W/).map(function(part) {
var x = parseInt(part, 10);
return isNaN(x) ? part.toLowerCase() : x;
});
}
This is not the most performance-oriented solution: the split-parse function will be repeatedly called on the same strings as they are being sorted. If this becomes an issue (I don't really think so), one can optimize by having one run of conversion, creating an array of arrays, and then sorting that.

Constructing D3 Timeline Using A Comparison of YYYY-MM-DD Values

In D3 I am working on customizing and adding to this timeline: http://bl.ocks.org/rengel-de/5603464 by rengel Rengel. All has been going well until when recently I have been having a problem showing all of the events on my timeline from my JSON dataset. Instead of showing from 1970-1953, it shows only 1966-1953.
D3 Only Showing Partial Results from JSON
My dates in my JSON file are in YYYY-MM-DD format, and I am laying out the timeline using tracks. This function appends elements into these tracks and it sorts through the results from later to earlier dates (see code below). But for some reason, if I sort these JSON results backwards, my dates only start at 1966, and if I sort forward() they only start half way through (1958) from the opposite side. I have been thinking this is happening because the dates aren't being calculated properly.
Here is the compareDescending function that checks each pair of dates:
function compareDescending(item1, item2) {
// Every item must have two fields: 'start' and 'end'.
// Read the dataset in and then compare the dates of the first value with the next value
var firstdatestartdesc = new Date(item1.DateStart);
var seconddatestartdesc = new Date(item2.DateStart);
// later first
var result = new Date(item1.DateStart) - new Date(item2.DateStart) ;
if (result < 0) { return 1; }
if (result > 0) { return -1; }
return 0;
var oneDay = 24*60*60*1000; // hours*minutes*seconds*milliseconds
var firstdatefinishdesc = new Date(item1.DateFinish);
var seconddatefinishdesc =new Date(item2.DateFinish);
result = new Date(item2.DateFinish) - new Date(item1.DateFinish);
if (result < 0) { return 1; }
if (result > 0) { return -1; }
return 0;
}
I am then using the calculateTracks function to sort through:
function calculateTracks(item, sortOrder, timeOrder) {
var i, track;
sortOrder = sortOrder || "descending"; // "ascending", "descending"
timeOrder = timeOrder || "backward"; // "forward", "backward"
function sortBackward() {
// older items end deeper
data.projects.forEach(function (item) { /
for (i = 0, track = 0; i < tracks.length; i++, track++) {
if (item.DateFinish < tracks[i]) { break; }
}
item.track = track
tracks[track] = item.DateStart;
});
}
//won't need to use this when we have sort backward instead
function sortForward() {
// younger items end deeper
data.projects.forEach(function (item) {
for (i = 0, track = 0; i < tracks.length; i++, track++) {
if (item.DateStart > tracks[i]) { break; }
}
item.track = track;
tracks[track] = item.DateFinish;
});
}
if (sortOrder === "ascending")
data.projects.sort(compareAscending);
else
data.projects.sort(compareDescending);
if (timeOrder === "forward"){
;
sortForward();
}else{
sortBackward();
}
}
While debugging this, I can see that changing the value of the "result" variable produces different layouts, so that's why I think that it isn't computing dates properly. So I have then tried a number of other ways to compare dates, but no luck yet. (Actually in one case, the rectangles displayed from 1970 back to 1953, but instead of 'stacking' in lanes, each rectangle was added below the preceding rectangle, but the rectangles ended up below the x-axis without stacking properly. The following adjustments were tried with the result variable:
var oneDay = 24*60*60*1000; // hours*minutes*seconds*milliseconds
var result = Math.round(firstdatestartdesc.getTime() - seconddatestartdesc.getTime());
var result = Math.round(Math.round(firstdatestartdesc - seconddatestartdesc)/(oneDay));
var result = Math.round((firstdatestartdesc - seconddatestartdesc)/(oneDay));
var result = Math.round((firstdatestartdesc - seconddatestartdesc)/(oneDay));
How might I get all of the rectangles to display, instead of the results starting only half way through the dataset?
Thanks in advance.
Nothing to do with dates, as thanks to the power of that fully armed and operational jsfiddle, your problem was this:
vis.selectAll ("g:not(.xaxis)")
should be
vis.selectAll ("g.rectclass")
g:not(.xaxis) only excludes the xaxis, but not the child g elements that hold the axis labels. So your first X data points are getting joined to these g elements that hold these labels. Since they already exist, they don't get picked up by the .enter() clause and your first X results are discarded (which is also why your missing results changed depending on which end you started sorting from.)

Loop through array and adding sums of each section

So I have 11 checkboxes that are split up into 4 different categories. Each category has 3 check-boxes to choose from except for the last, which has 2. I want to check if a check-box within each category is checked and find out how many of them are checked within that category. I might be over thinking this one but so far I have this as my JS:
//I initially receive the checkbox values as a string that has 1 for checked and 0 for not checked.
var split_string = checkbox_string.split(",").map(Number);
console.log(split_string);
var sec = [];
var total = 0;
var split_int=[];
var sliced = 0;
for (var i = 0; i <= 3 ; ++i) {
sec[i] = split_string.splice(0,3);
console.log(sec[i]);
for(var j = 0; j < sec[i].length; ++j){
sliced = sec[i][j];
total += sliced;
}
console.log("total= "+ total);
window['section' + i] = total;
}
So as of right now I'm pretty close, although I'm sure there is a simpler way of doing this. I split the string into 4 arrays (ex.[1,0,1] [0,0,1] [1,1,1] [1,0]). Then I take each individual number from each array and add it to the total.
As of right now it will return the 1st three added, then it returns the 2nd three added to the first three on its 2nd loop. So for example total=2 the first time around then total=3 the 2nd time around, but I want total the 2nd time around to be only based on the 2nd array (so it would be 1 if following the ex. above).
function summer(p,c,i) {
if( i%3==0 ) p.push(0);
p[p.length-1] += c;
return p;
}
var split_string = [1,0,1,0,0,1,1,1,1,1,0];
split_string.reduce(summer,[]); // [2, 1, 3, 1]
Well I'm dumb, all I needed to add was total = 0 at the bottom of the array. But I'd still be interested if there is better/more simple ways of doing this.

Nested loop in JavaScript/jQuery not working

Im calling a for loop inside a for loop and its not working, here's the code :
function PopulateMonths() {
for (var m = 0; m < 12; m++) {
var $month = $('.d-month').clone();
$month.find('.d-header').text(m);
$month = PopulateDays($month);
$month.appendTo('#diary').show();
$month = null;
}
}
function PopulateDays($month) {
for (var d = 0; d < 30; d++) {
var $row = $('.d-row').clone();
$row.find('.d-day').text(d);
$row.appendTo($month).show();
$row = null;
}
return $month;
}
If I call PopulateDays manually 12 times it works fine, as soon as I try to loop 12 times using PopulateMonths() the page crashes, CPU usage goes through the roof so im assuming a lot of work is going on.
What am I missing?
I've had to tackle a very similar issue before. It's because when you are cloning the element, you are also cloning their classes etc. And then you insert the cloned item into the document.
The next time you try to look for an element with that class, it will find two instances - the original one, and the one you cloned in the previous step. Both will be cloned again, and now you have 4 elements on the page. So you're basically doubling the number of elements on each iteration, and doing it 12 times for days, and 30 times for months.
2^12 = 4096
2^30 = 1,073,741,824
These are just rough estimates of how large it can grow. I haven't done any further analysis to find the exact numbers, but basically the exponential growth is eating up the CPU and crashing your browser.
I believe because you are cloning the set of month elements in this line:
var $month = $('.d-month').clone();
and then in the populate days function appending 30 rows to the month in this line:
$row.appendTo($month).show();
Then appending the month to the diary in this line:
$month.appendTo('#diary').show();
Then next time this line executes there is another month that get cloned in this line:
var $month = $('.d-month').clone();
As well as cloning the rows you just appended over again in this line:
var $row = $('.d-row').clone();
Executing this in a loop increases the load substantially.

Categories

Resources