Sorting an array in javascript based on date - javascript

I'm trying to parse multiple subreddit feeds in a Google Script. I can call this Google Script (redditFeeds()) and it returns the title, link, and date to my spreadsheet. However, I want to sort the posts by date so I can see the most recent posts first. I've tried using sort() on the array in various ways and can't get anything sort by descending date. I've even tried converting the date to a Date object and that didn't fix it.
function redditFeeds() {
var entries_array = [];
var subreddit_array = ['https://www.reddit.com/r/funny/top/.rss','https://www.reddit.com/r/news/top/.rss']
for (var s = 0; s < subreddit_array.length; s++) {
var xml = UrlFetchApp.fetch(subreddit_array[s]).getContentText();
var document = XmlService.parse(xml);
var root = document.getRootElement();
var atom = XmlService.getNamespace('http://www.w3.org/2005/Atom');
var entries = document.getRootElement().getChildren('entry', atom);
for (var i = 0; i < entries.length; i++) {
var title = entries[i].getChild('title', atom).getText();
var title = entries[i].getChild('link', atom).getText();
var link = entries[i].getChild('link', atom).getAttribute('href').getValue();
var date = entries[i].getChild('updated', atom).getValue();
entries_array.push([title, link, date]);
}
}
//return entries_array;
//doesn't work
//entries_array.sort(function(a,b) {
// return a.date - b.date;
//});
//also not working
return entries_array.sort(function(a,b) {
new Date(a.date).getTime() - new Date(b.date).getTime();
});
}

I think you want the below, assuming entries_array looks like I think it does. I have no idea what start was supposed to be in your code... I think each entry in entries_array is an array with three members in it, the third being some sort of representation of a date. If it's one that can be parsed by new Date, then this code should work:
return entries_array.sort(function (a, b) {
return new Date(a[2]) - new Date(b[2]);
});
If that's not right, please share what entries_array looks like.

I see a return missing, in the inner sort function and you should not need the getTime()
return entries_array.sort(function(a,b) {
return new Date(a.start) - new Date(b.start);
});

An easy way of sorting date objects is by converting them into UNIX time stamps using dateObj.getTime(). This creates an integer of the seconds since midnight on New Years day 1970. It's very useful if you are working in multiple time zones.

Related

I want to avoid duplicate dates in google sheets by using a script

I just signed up and need help with a problem, I am new to the google app scripts and I am struggling to create a script to avoid duplicate date.
The sheet will capture data once a day and to avoid duplicate dates I am trying to write a script.
I have looked at different methods, tried arrays and that also wont seem to work.
I created a small test site to explain here with the current issue I am facing.
Below is the code when the user clicks a save button, please not I am only struggling with the if statement. I get all the dates but I am unable to break it into separate dates in order to do the if statement.
In your code the variable values is indeed an array retrieved from your sheet using getValues()
You can manipulate that array as you loop through it removing the duplicate based on your variable names date or load into a separate array
var i = 0;
var lenValues = values.length;
var newArray = [];
for (i = 0; i < lenValues; i++) {
if (date !== values[i]) {
newArray.push(values[i]);
}
}
Now, dates can be tricky, I would use the debugger and set a breakpoint to inspect the data format stored in the values variable and adjust accordingly.
Once you have the new array, you may decide to write those values to another sheet
writeDataToSheet(newArray, "Target sheet name");
// Writes a 2D array of data to sheet
function writeDataToSheet(data, sheetName) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
goToSheet(sheetName, ss);
var sheet = ss.getActiveSheet();
var range = sheet.getRange("A1:A");
range.clear();
// write date to active sheet starting at the 2nd row
sheet.getRange(1, 1, data.length, data[0].length).setValues(data);
return sheet.getName();
}
function goToSheet(sheetName, ss) {
ss.setActiveSheet(ss.getSheetByName(sheetName));
}
Now, if all you want to do is alert the user the data already exists try this instead:
var i = 0;
var found = false;
var lenValues = values.length;
for (i = 0; i < lenValues; i++) {
if (date == values[i]) {
found = true;
break;
}
}
Put this before your if statement and change to:
if (found) {
}
This code will work to remove duplicates. My original dates are in C9:C16
The problem here is that it has converted the dates into strings, you may need to convert back to dates.
function removeDuplicate(){
var sheet = SpreadsheetApp.getActive().getActiveSheet();
let originalDates = sheet.getRange('C9:C16').getDisplayValues().flat();
console.log(originalDates);
let datesNoDup = originalDates.filter((date,i) => originalDates.indexOf(date) == i);
console.log(datesNoDup);
}
7:14:26 AM Notice Execution started
7:14:27 AM Info [ '2/1/2011',
'2/1/2011',
'2/25/2011',
'3/17/2011',
'7/25/2011',
'10/19/2011',
'3/17/2011',
'7/25/2011' ]
7:14:27 AM Info [ '2/1/2011',
'2/25/2011',
'3/17/2011',
'7/25/2011',
'10/19/2011' ]
7:14:27 AM Notice Execution completed
```

Get last value from an array using Google Apps Script

I need to get last value from an array and I keep getting this error when I use slice
TypeError: Cannot find function slice in object Sun Jul 23 2017 00:00:00 GMT+0100 (BST). (line 15, file
If I use length -1 I get NaN.
This is the code I am using it.
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Data");
var range = sheet.getDataRange();
var values = range.getValues();
var today = new Date(Date.now());
today.setHours(0,0,0,0);
Logger.log(today);
var setTotal;
var getToday = values[4].map(Number).indexOf(+today);
Logger.log(getToday);
for (i = 0; i < values.length; i++) {
var getTotal = values[i][getToday];
Logger.log(getTotal.slice(-1)[0]);
}
}
... and this is the table
full table
So I need when it match the current day (today) to retrieve last value from that array (column) which is the Total for that day.
Thank you!
Kind regards,
getTotal is always already a singular value.
Also the way you find your column is brittle due to timezones because you normalize only one date.
If you do it with both dates (which needs to be handled safely unless you want to do index constraints) your column finding approach works.
function getTodaysTotal() {
function toUtcMidnight(date) {
try {return date.setHours(0,0,0,0);}
catch(e) {return;}
}
var values = SpreadsheetApp
.getActiveSpreadsheet()
.getSheetByName("Data")
.getDataRange()
.getValues();
var today = toUtcMidnight(new Date());
var todaysColumn = values[4].map(toUtcMidnight).map(Number).indexOf(+today);
var output = values[values.length - 1][todaysColumn];
return values[values.length - 1][todaysColumn];
}
You can use the method .pop() that returns and removes the last element from an array.
Make a copy of the original array first and use .pop() method and assign it to a new value.
var myArray = myArrayCopy
var lastArrayObject = myArrayCopy.pop()

Javascript in Zapier to return multiple values for posting to Airtable database

I am trying to write some javascript in Zapier which will read two dates and then return an array of all dates between those dates in such a way that they can then be used to create multiple dated records in Airtable (a database). From the Zapier help it says that if you return an array of objects then the following steps will be processed for each.
I have managed to get code which returns the data I wan but it can't be correct because if I try to create the database records only one is created - with all the dates in (so it will only work if output to a text field - not a date). Here's my code attempt:
var fromDate = new Date(inputData.from);
var toDate = new Date(inputData.to);
var output =[];
var i = 1;
do {
var useDate = new String(fromDate.toISOString())
output.push(useDate);
console.log(fromDate);
fromDate.setDate(fromDate.getDate() + 1);
i++
}
while (fromDate <= toDate);
console.log(output);
return{output};
The subsequent step does see the output variable - but it is treated as one value as I said above.
Does anyone have any ideas?
Thanks Juan
That sorted it - or at least it did after removing the return - here is the working code:
var fromDate = new Date(inputData.from);
var toDate = new Date(inputData.to);
var output =[];
var i = 1;
do {
var useDate = new String(fromDate.toISOString())
var dateObject = {};
dateObject.date = useDate;
output.push({dateObject});
fromDate.setDate(fromDate.getDate() + 1);
i++
}
while (fromDate <= toDate);
It looks like you're returning an object, not an array of objects:
return{output};
Also, your do/while statement is creating an array of strings, not objects. In your do block, instead of pushing the useDate string to the output array, you should construct a simple object and push that to the output array.
So instead of pushing '2016-09-28T00:00:00.000Z' each time the loop runs, you should push something like {date: '2016-09-28T00:00:00.000Z'}.
Your do block should look something like this:
do {
var useDate = new String(fromDate.toISOString());
var dateObject = {};
dateObject.date = useDate;
output.push(dateObject);
fromDate.setDate(fromDate.getDate() + 1);
i++
}
This way, output will be an array of objects:
[
{
"date": "2016-09-28T00:00:00.000Z"
},
{
"date": "2016-09-29T00:00:00.000Z"
},
{
"date": "2016-09-30T00:00:00.000Z"
}
]

How to sort a set of data by date in appcelerator

Does anybody know how to sort out a set of data in appcelerator? I tried out with some sample code and it worked fine. But while implementing in my scenario it's not working. In my case I added data into the DB and sorted it by calling data from DB. Date format is like this "yyyy-mm-dd hh:mm:ss"
Here is my code:
var DummyData = [];
var isDatess=true;
var sampleData= Alloy.createCollection('samplePage');
sampleData .fetch({query:"SELECT * FROM dummyValfromDB"});
if(sampleData.length > 0){
isDatess=true;
for (var i = 0; i < sampleData.length;i++) {
var did = sampleData.at(i).get('did');
var dummyName = sampleData.at(i).get('dummyName');
var dummydate= sampleData.at(i).get('dummydate');
var dummyuid= sampleData.at(i).get('dummyuid');
sampleData.push({
"label_dummy_name": { text: dummyName},
"label_dummydate":{text: dummydate},
"label_dummyuid":{text: dummyuid},
});
}
DummyData.sort(sorting);
}
function sorting(a,b){
var dateA = new Date(a.label_dummydate).getTime();
var dateB = new Date(b.label_dummydate).getTime();
var result="";
if(isDatess)
result=dateA > dateB ? 1 : -1;
else
result=dateA < dateB ? 1 : -1;
return result;
};
$.dummyList.sections[0].setItems(DummyData);
I got the answer. NaN shows while executing and it resolved by adding text. Find the answer i got below.
function sorting(a,b) {
var valA = a.label_dummydate.text;
var valB = b.label_dummydate.text;
var dateA = new Date(val_a).getTime();
var dateB = new Date(val_b).getTime();
var result="";
if(isDatess)
result=dateA > dateB ? 1 : -1;
else
result=dateA < dateB ? 1 : -1;
return result;
};
Thanks for all your help. I think it may help somebody....Cheers !!!!
For your use case, can you use ORDER BY in your SQL query to sort the data by date or date time either ascending or descending?
This is only a quick glance, but it looks like you are using a.label_dummydate in your date constructor in your sorting function when you should be using a.label_dummydate.text. What you are using is an object literal as opposed to the string content you want so its making an invalid date which won't compare correctly
Sorting can be done by using the Underscorejs library which is available built-in with Alloy.
You can use the _.sortBy() for you case. Refer this for usage
Also this post specifically talks about sorting dates using underscore sortBy.
Array with object sorting with Underscore sortBy
Alloy has moment.js built-in, in my opinion it is easier than Date (both to work with and read the code), also it provides a lot of utilities to compare two dates; if you are interested into internationalization also it is quite easy to do it.

Javascript - create array between two date objects

Question
I am attempting to build an array between two JS objects. It appears that my objects are being created correctly, and in fact that the code below is running.
The unexpected behavior is that every object in my output array is transforming to match the last date that I looped through. i.e. if I loop, whatever my todate_dateobjis, I get an entire array of just that value.
I have to do some debugging wrt the actual start/end dates being correct, but I can handle that -- what I'm stymied by is the behavior described above.
I am very new to javascript. I imagine this is some issue with mutation? Any guidance would be appreciated.
I left the console logs in just because why take them out?
Code
function build_dateobjs_array(fromdate_dateobj, todate_dateobj) {
// return an array of dateojects from fromdate to todate
var current_date = fromdate_dateobj;
var return_array = []
while (current_date <= todate_dateobj) {
return_array[return_array.length] = current_date; // I have read that this is generally faster that arr.push()
var tomorrow = new Date(current_date.getTime() + 86400000);
console.log('tomorrow: ', tomorrow);
current_date.setTime(tomorrow);
console.log('current_date: ', current_date)
console.log("build_dateobjs_array : ", return_array);
};
return return_array;
};
Date objects are mutable. This line:
current_date.setTime(tomorrow);
...changes the state of the Date object that current_date refers to, which you never change.
So you're storing the same object repeatedly in return_array. Instead, make a copy of the Date:
return_array[return_array.length] = new Date(+current_date);
Also, it's probably best to change
var current_date = fromdate_dateobj;
to
var current_date = new Date(+fromdate_dateobj);
so you're not modifying the Date that was passed in.
Side note: There's no need for the round-trip to milliseconds, simply:
function build_dateobjs_array(fromdate_dateobj, todate_dateobj) {
// return an array of dateojects from fromdate to todate
var current_date = new Date(+fromdate_dateobj);
var return_array = [];
while (current_date <= todate_dateobj) {
return_array[return_array.length] = new Date(+current_date);
current_date.setDate(current_date.getDate() + 1);
};
return return_array;
}
(There's also no reason to put a ; at the end of a function declaration.)

Categories

Resources