js find min difference in date array - javascript

I have a sorted array:
[new Date('2017-01-02'), new Date('2017-01-07'), new Date('2017-01-09'), new Date('2017-01-17')]
Now I want to find the minimum time difference occuring in the array between any two adjacent elements. eg in this case:
new Date('2017-01-09').getTime() - new Date('2017-01-07').getTime()
is there some elegant way with map or something similar or do I have to loop, remember the smalles interval so far and then replace the value if a smaller one occurs?
Current solution:
let timestamps = Gps.find().map(doc => doc.timestamp);
timestamps.sort();
let minimumDifference;
let previousTimestamp;
timestamps.forEach(timestamp => {
if(!previousTimestamp) {
previousTimestamp = timestamp;
}
else{
let difference = timestamp.getTime() - previousTimestamp.getTime();
if(!minimumDifference || minimumDifference > difference){
minimumDifference = difference;
}
previousTimestamp = timestamp;
}
});

I would like to go back into olden days. plain old javascript. Not creating unnecessory copy
var timestamps = [1,2,5,9];
timestamps.sort();
var result = timestamps[timestamps.length-1];
for(var i=1;i<timestamps.length;i++){
result = (timestamps[i]-timestamps[i-1])<result?(timestamps[i]-timestamps[i-1]):result;
}
take mills and proceed same way

Related

Sorting an array in javascript based on date

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.

Reorganizing multidimensional arrays based on multiple value characteristics in JavaScript?

I'm having trouble organizing this data the way I would like it to. On my pages, a few things happen that I know work...
Some PHP spits out a multidimensional associative array. The top level of this array is an array of regions. Each region is an array of timezones.
Some more PHP creates a second multidimensional associative array. The top level of this array is an array of regions. Each region is an array of UTC offsets.
Both arrays are generated in the same order from the same data. This means that $offsets["region"][0] will have be based on the same timezone as $timezones["region"][0].
Both arrays are encoded into JSON and passed to my JavaScript.
I have the following JavaScript code...
var tempCurrentTimezoneArray = timezoneArray[ $("select[name='region_selector']").val() ];
var tempCurrentOffsetArray = timezoneOffsetArray[ $("select[name='region_selector']").val() ];
var groupedTimezones = {};
var groupedOffsets = {};
for (counter = 0; counter < tempCurrentOffsetArray.length; counter++) {
significantOffset = tempCurrentOffsetArray[counter].substr(tempCurrentOffsetArray[counter].length - 2);
if (!(significantOffset in groupedTimezones)) {
groupedTimezones[significantOffset] = [];
groupedOffsets[significantOffset] = [];
}
groupedTimezones[significantOffset].push(tempCurrentTimezoneArray[counter]);
groupedOffsets[significantOffset].push(tempCurrentOffsetArray[counter]);
}
var offsetArray = [];
for (var property in groupedTimezones) {
if (!groupedTimezones.hasOwnProperty(property)) {
continue;
}
groupedTimezones[property].sort();
groupedOffsets[property].sort();
offsetArray.push(parseInt(property));
}
offsetArray.sort();
var currentTimezoneArray = [];
var currentOffsetArray = [];
for (counter = 0; counter < offsetArray.length; counter++) {
currentTimezoneArray = currentTimezoneArray.concat(groupedTimezones[offsetArray[counter]]);
currentOffsetArray = currentOffsetArray.concat(groupedOffsets[offsetArray[counter]]);
}
In the top two lines I remove all of the timezone data not pertaining to the region selected on the page. This means that I am left with 2 single-dimensional arrays. Any given index of either array relates directly to the other array. I.E....
tempCurrentOffsetArray[0] is the UTC offset of the timezone found at tempCurrentTimezoneArray[0].
The rest of this code is intended to complete the following tasks...
Group timezones and offsets by their UTC offset.
Organize each offset group in alphabetical order.
Create two arrays where values are organized first by UTC offset and second by alphabetical order.
The problem I'm having is that on some regions I receive almost perfect listings,and on others I receive some listings with a seemingly random number of undefined values, and I'm not sure why. Can anyone identify the syntactical or logical errors in my code?
JSON of tempCurrentTimezoneArray input data here
JSON of tempCurrentOffsetArray input data here
You think still too complicated. It is a mess to keep these two Arrays in sync, better use one Array with objects.
var region_selector = $("select[name='region_selector']").val();
var tempCurrentTimezoneArray = timezoneArray[ region_selector ];
var tempCurrentOffsetArray = timezoneOffsetArray[ region_selector ];
//consolidate the Arrays
var data = []; //create a new Array `data`
for(var i = tempCurrentOffsetArray.length; i--; ){
//write into Array `data` at index `i` an object, containing these properties:
//`timezone`, `offset` and `offsetValue`, and their respective values
data[i] = {
timezone: tempCurrentTimezoneArray[i],
offset: tempCurrentOffsetArray[i],
//the + at the beginning converts the value behind that into a Number, like parseFloat() would do
offsetValue: +tempCurrentOffsetArray[i].match(/^GMT([+-]\d+(?:\.\d+)?)$/)[1]
}
}
//sorter-function for data to sort the values by offsetValue ASC first, then by timezone ASC
function sortedByOffset(a, b){
return a.offsetValue - b.offsetValue || a.timezone.localeCompare(b.timezone);
}
//you should do this as late as possible, usually after the filtering
data.sort(sortedByOffset);
If you insist on the two output-Arrays
var currentTimezoneArray = data.map(d => d.timezone);
var currentOffsetArray = data.map(d => d.offset);
otherwise this is imo more flexible
//utilities to fetch a property off the object
var getTimezone = d => d.timezone;
//aka function getTimezone(d){ return d.timezone }
var getOffset = d => d.offset;
//aka function getOffset(d){ return d.offset }
//example usages:
data.filter(d => d.offset === "GMT-5").map( getTimezone );
data.filter(d => d.offsetValue >= -2 && d.offsetValue <= -5 ).map( getOffset );
taking the first example; thinking in terms of a SQL-statement this would be
SELECT timezone FROM data WHERE offset = "GMT-5"
get me the timezone-values for each entry where the offset is GMT-5
you start with an Array containsing all values data then you get the subset you are interested in (in this case every entry, with the offset "GMT-5") by filtering.
Now you have an Array containing all values you are intersted in, but still the whole objects; like a SELECT * FROM ...
the map() function calls the function getTimezone() on every entry in this subset and returns another Array containing only the timezone-values.
The second example defines a range for the filter (every entry from GMT-2 to and including GMT-5 and every GMT in between) and returns for these entries the offset-protperty.
I discovered the issue with my code. There were actually three issues the first being on line 6. After looking over the data one more time I realized that some of the values had offsets that were floating point integers or had more than two significant digits. The new line 6 is...
significantOffset = tempCurrentOffsetArray[counter].replace(/[^\d.-]/g, '');
The second issue with my code also had to do with parsing floating integers. On line 21 we need to use parseFloat instead of parseInt. The new line 21 is...
offsetArray.push(parseFloat(property));
The third issue lies on line 23. sort() needs to be told how to sort the integers. This is the new line 23...
offsetArray.sort(function(a, b){return a-b});
The final code looks like this...
var tempCurrentTimezoneArray = timezoneArray[ $("select[name='region_selector']").val() ];
var tempCurrentOffsetArray = timezoneOffsetArray[ $("select[name='region_selector']").val() ];
var groupedTimezones = {};
var groupedOffsets = {};
for (counter = 0; counter < tempCurrentOffsetArray.length; counter++) {
significantOffset = tempCurrentOffsetArray[counter].replace(/[^\d.-]/g, '');
if (!(significantOffset in groupedTimezones)) {
groupedTimezones[significantOffset] = [];
groupedOffsets[significantOffset] = [];
}
groupedTimezones[significantOffset].push(tempCurrentTimezoneArray[counter]);
groupedOffsets[significantOffset].push(tempCurrentOffsetArray[counter]);
}
var offsetArray = [];
for (var property in groupedTimezones) {
if (!groupedTimezones.hasOwnProperty(property)) {
continue;
}
groupedTimezones[property].sort();
groupedOffsets[property].sort();
offsetArray.push(parseFloat(property));
}
offsetArray.sort(function(a, b){return a-b});
var currentTimezoneArray = [];
var currentOffsetArray = [];
for (counter = 0; counter < offsetArray.length; counter++) {
currentTimezoneArray = currentTimezoneArray.concat(groupedTimezones[offsetArray[counter]]);
currentOffsetArray = currentOffsetArray.concat(groupedOffsets[offsetArray[counter]]);
}

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.)

Constructing and getting an Array in Jquery

I have created a function that counts the week difference between two dates.Users must pick a Saturday or Sunday (start and end of week) The next step, is to have the document create elements that enumerate each week within the selected range.
Here is my JSFiddle
http://jsfiddle.net/jafaoej5/1/
var $arr = [];
while(lowEnd <= totalweeks.innerHTML){
arr.push(lowEnd++);}
console.log( $( "arr" ).get()) ;
});
This is some code that I am trying to use to console log the total number in weeks. From there I will do a math operation to do the conversion operations with UTC time. The problem is that I can't get my array. How can I get my array?
You're creating $arr but pushing into arr ??
This is how I think it should be:
var $arr = []; // Or just use 'arr' instead of '$arr'
while (lowEnd <= totalweeks.innerHTML) {
// The above 'while' also needs modification because you're using lowEnd
// as an integer whereas innerHtml will return a string
// MAYBE this is what you want:
// var totalWeeks = parseInt(totalweeks.innerHTML) || 0;
// while (lowEnd <= totalWeeks) {}
$arr.push(lowEnd++);
console.log($arr);
});
As for the get() function, I don't know what you were trying to do.
If you want difference in weeks you can do just that:
var firstDate = new Date("7/11/2010"); // get those through datepicker
var secondDate = new Date("12/12/2010");
// calculate difference in timestamp (miliseconds)
var timestampDiff = Math.abs(secondDate.getTime() - firstDate.getTime());
// convert the difference into weeks, use ceil to round up (started weeks), use floor to roun down (full weeks)
var weeksDiff = Math.ceil(timestampDiff / (1000 * 3600 * 24 * 7));
console.log(weeksDiff)​;
As for the array: $arr and arr are not the same, I would suggest using $ in naming variables that are objects, so in this case arr is better.
It is not a good idea to limit oyor loop with innerHtml because you will get an error if it will be something other than number.
// declare an array
var arr = [];
while(lowEnd <= parseInt(totalweeks.innerHTML)){
arr.push(lowEnd++);}
});
// print it once it's complete
console.log(arr);

Multi-dimensional array and timestamp

Here is the code :
var array = [];
$('.body-watch-logo').each(function () {
array[]['evendId'] = $(this).data('event');
array[]['timestamp'] = $(this).data('timestamp');
$now = new Date();
$outStr = now.getHours()+':'+now.getMinutes();
alert($outStr);
if(array[]['timestamp'] == $outStr) {
alert('Tring Tring Tring');
//do something here
}
$i++;
});
.body-watch-logo has several events in it with attributes eventId and startTime. So I want to store this information in array. Then compare the startTime which has only Hour and minute with current-time. If they are equal give an alert. Does anyone have an idea how to do this? Use Ajax may be. Please suggest.
You incremented i, but never initialized it or used it as your array index. But you don't need to do either, since .each() passes the index as an argument to the iteration function. See
http://api.jquery.com/jQuery.each/
The elements of the array are better implemented as objects, not sub-arrays.
var array = [];
$('.body-watch-logo').each(function (i) {
array[i] = { event: $(this).data('event'),
timestamp: $(this).data('timestamp')
};
$now = new Date();
$outStr = now.getHours()+':'+now.getMinutes();
alert($outStr);
if(array[i].timestamp == $outStr) {
alert('Tring Tring Tring');
//do something here
}
});

Categories

Resources