I wanted to sort an array of objects using js. Here is what I have implemented.
var employees = []
employees[0] = {
retiredate: "01/12/2014"
}
employees[1] = {
retiredate: "29/01/2015"
}
employees[2] = {
retiredate: "05/12/2014"
}
employees[3] = {
retiredate: "08/12/2014"
}
employees[4] = {
retiredate: "11/12/2014"
}
employees[5] = {
retiredate: "14/01/2015"
}
employees[6] = {
retiredate: "03/12/2014"
}
employees[7] = {
retiredate: "16/01/2015"
}
employees[8] = {
retiredate: "19/01/2015"
}
employees[9] = {
retiredate: "22/01/2015"
}
employees[10] = {
retiredate: "28/01/2015"
}
employees[11] = {
retiredate: "23/01/2015"
}
employees[12] = {
retiredate: "15/01/2015"
}
//console.log(periodesSorted);
console.log("START ... ")
employees.sort(function(a, b) {
var dateA = new Date(a.retiredate),
dateB = new Date(b.retiredate)
return dateA - dateB //sort by date ascending
})
for (ind2 = 0; ind2 < employees.length; ind2++) {
console.log(employees[ind2].retiredate)
}
console.log("End ... ")
In firefox the array of retiredate is well sorted.
In chrome, I have the following results
01/12/2014
15/01/2015
05/12/2014
08/12/2014
11/12/2014
14/01/2015
29/01/2015
16/01/2015
19/01/2015
22/01/2015
28/01/2015
23/01/2015
03/12/2014
The results are not sorted. Where did I go wrong in the codes?
Can anyone suggest a fix for this ?
Regards
You can use
employees.sort(function (d1, d2) {
function parseDate(str) {
var parts = str.match(/(\d+)/g);
// assumes M/D/Y date format
return new Date(parts[2], parts[0]-1, parts[1]); // months are 0-based
}
return parseDate(d1.retiredate) - parseDate(d2.retiredate);
});
Here Is example Link
Instead of this:
new Date(a.retiredate)
Make it like this to convert dd/mm/yyyy to yyyy-mm-dd before creating the date:
new Date(a.retiredate.replace( /(\d{2})\/(\d{2})\/(\d{4})/, "$3-$2-$1") );
Working JSFiddle:
http://jsfiddle.net/inanda/csz56b0q/1/
In our case you need convert date to format mm/dd/yyyy, you can do it like this
employees.sort(function(a, b) {
var toDate = function (date) {
var res = date.split('/');
return new Date(res[2], res[1], res[0]).getTime();
// getTime returns the number of milliseconds
// or you can use + before new Date..
};
return toDate(a.retiredate) - toDate(b.retiredate);
})
Example
Personally I would avoid all the re-parsing & date construction (84 times in your sample);
// prepare the data by appending a date from a reformatted string
for (var i = 0; i < employees.length; i++) {
var dateString = employees[i].retiredate;
employees[i]._date = new Date(dateString.substr(6, 4) + "-" + dateString.substr(3, 2) + "-" + dateString.substr(0, 2));
}
// sort without conversion
employees.sort(function(a, b) {
return a._date - b._date;
})
Related
Date can be in any format 25.10.2018 or 25.10.18 or 25-12-2018 or 25-12-18, need to change this date to 25/10/2018 this format only.
The user can input date in any above format, I need to distinguish first in which format then needs to change its format to the desired format.
I do not want to use any 3rd Party JavaScript file.
You can easily do this using momentjs.
Check below working examples:
let d1 = "25.10.2018";
console.log(moment(d1, "DD.MM.YYYY").format("DD/MM/YYYY"));
let d2 = "25.10.18";
console.log(moment(d2, "DD.MM.YY").format("DD/MM/YYYY"));
let d3 = "25-12-2018";
console.log(moment(d3, "DD-MM-YYYY").format("DD/MM/YYYY"));
let d4 = "25-12-18";
console.log(moment(d4, "DD-MM-YY").format("DD/MM/YYYY"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.1/moment.js"></script>
So your original date have included special character like .,- .So you can split with that characters and I add 0 for your month and date 1 digit.For year format , use new Date to get correct year even two digit have provided ....
var d = '12-4-88'; // '25.10.2018'; or 25.10.18 or 25-12-2018
d = d.split(/[.\-_]/);
d.forEach((v,k) => {
if(v < 10) d[k] = 0 + v;
if(k == 2 && v.length == 2) {
var year = new Date(v+"-01-01");
d[k] = year.getFullYear();
}
})
console.log(d[0] + '/' + d[1] + '/' + d[2]);
You will need Date to preserve full year as two digits year value evaluates invalid date.
function parse(str) {
var result = {
'input': str,
'output': null
};
var tmp = str.split(/[\.|\-]/);
if (tmp && 3 === tmp.length) {
if (2 === tmp[2].length) {
tmp[2] = new Date().getFullYear().toString().substr(0, 2) + tmp[2];
}
if (1 === tmp[1].length) {
tmp[1] = '0' + tmp[1];
}
result.output = tmp.join('/');
}
return result;
}
console.log(parse("25.10.2018"));
console.log(parse("25.10.18"));
console.log(parse("25-10-2018"));
console.log(parse("25-10-18"));
console.log(parse("25.1.2018"));
console.log(parse("05.10.2018"));
function replaceAll(string, search, replacement) {
return string.replace(new RegExp(search, 'g'), replacement);
};
const newDate = replaceAll(oldDate, '.', '/');
String.prototype.replaceAll = function(str1, str2, ignore)
{
return this.replace(new RegExp(str1.replace(/([\/\,\!\\\^\$\{\}\[\]\(\)\.\*\+\?\|\<\>\-\&])/g,"\\$&"),(ignore?"gi":"g")),(typeof(str2)=="string")?str2.replace(/\$/g,"$$$$"):str2);
}
"25.10.2018".replaceAll(".", "/");
There JSON:
[{"source":"2016-11-02","sourcecount":38},{"source":"2016-11-01","sourcecount":30},{"source":"2016-11-02","sourcecount":30},{"source":"2016-11-03","sourcecount":30}]
As in JavaScript to get the maximum and minimum date of it?
var array = [{"source":"2016-11-02","sourcecount":38},{"source":"2016-11-01","sourcecount":30},{"source":"2016-11-02","sourcecount":30},{"source":"2016-11-03","sourcecount":30}];
var max = null;
var min = null;
for (var i = 0; i < array.length; i++) {
var current = array[i];
if (max === null || current.source > max.source) {
max = current;
}
if (min === null || current.source < min.source) {
min = current;
}
}
document.getElementById('maxResult').innerHTML = max.source;
document.getElementById('minResult').innerHTML = min.source;
Max: <span id="maxResult"></span><br/ >
Min: <span id="minResult"></span>
You could do something like this, provided your date format is "yyyy-MM-dd".
Convert the date string to dateKey. which always follow the ascending order as the dates proceed. 20160101(Jan 1st) is always less than 20161231(Dec 31st).
Keeping that in mind, just convert the dates to dateKey and map dateKeys to the object and just extract the max and min of the dateKeys and return the actual date.
var datesArray = [{
"source": "2016-11-02",
"sourcecount": 38
}, {
"source": "2016-11-10",
"sourcecount": 30
}, {
"source": "2016-11-31",
"sourcecount": 38
}, {
"source": "2016-01-01",
"sourcecount": 30
}];
var newObject = {};
var dates = datesArray.map(function(obj) {
var regEx = new RegExp(/-/g);
//Convert date to dateKey
var dateKey = parseInt(obj.source.replace(regEx, ""), 10)
newObject[dateKey] = obj;
return dateKey;
});
console.log("Max", newObject[Math.max(...dates)].source);
console.log("Min", newObject[Math.min(...dates)].source);
The good thing is, your date is in ISO 8601 format already. You can just simply do this,
var data = [{"source":"2016-11-02","sourcecount":38},{"source":"2016-11-01","sourcecount":30},{"source":"2016-11-02","sourcecount":30},{"source":"2016-11-03","sourcecount":30}];
var dateArr = data.map(function(v) {
return new Date(v.source);
});
// Sort the date
dateArr.sort(function(a, b) {
return a.getTime() - b.getTime();
// OR `return a - b`
});
// The highest date is in the very last of array
var highestDate = dateArr[dateArr.length - 1];
// The lowest is in the very first..
var lowestDate = dateArr[0];
Or you prefer to have your original object instead, then you can do,
var data = [{"source":"2016-11-02","sourcecount":38},{"source":"2016-11-01","sourcecount":30},{"source":"2016-11-02","sourcecount":30},{"source":"2016-11-03","sourcecount":30}];
data.sort(function(a,b) {
var date1 = (new Date(a.source));
var date2 = (new Date(b.source));
return date1 - date2;
});
// highest date is '2016-11-03'
var highestDate = data[data.length - 1].source
// lowest date is '2016-11-01'
var lowestDate = data[0].source
Try this
var data = [{"source":"2016-11-02","sourcecount":38},{"source":"2016-11-01","sourcecount":30},{"source":"2016-11-02","sourcecount":30},{"source":"2016-11-03","sourcecount":30}]
function compare(a,b) {
if (new Date(a.source) < new Date(b.source))
return -1;
if (new Date(a.source) > new Date(b.source))
return 1;
return 0;
}
data = data.sort(compare);
var minDate = data[0].source;
var maxDate = data[data.length - 1].source;
I'm having a difficulty showing my records from MongoDB. Basically I have some fields 'leaves_start' and 'leaves_end' in my MongoDB. This fields has the date range of the user's leave. See example below.
user_name : junel
leaves_start: 10/05/2015
leaves_end: 10/10/2015
I want to get all the records in my MongoDB if the current date (e.g 10/07/2015) is within the range of the record's leaves_start and leaves_end.
I already tried $gte and $lte but I'm a little bit confused on how to implement it on my current state.
Here's my sample method:
getTowerLeaveData_LV: function(dateToday,tower) {
var arr = LeavesCollection.find($or: [
{ leaves_start: { $lte: dateToday } },
{ leaves_end: { $gte: dateToday } } ],
leaves_approval_status: {$ne: 'Rejected'}}).fetch();
return arr
},
Here's my sample Mongodb Record
_____________________________________
name | leaves_start | leaves_end
_____________________________________
Junel | 10/01/2015 | 10/03/2015
_____________________________________
Jaycee | 10/03/2015 | 10/03/2015
_____________________________________
Tori | 10/05/2015 | 10/10/2015
_____________________________________
Ryan | 10/02/2015 | 10/05/2015
If the value of dateToday is 10/03/2015, then method should return the records of Junel, Jaycee and Ryan.
I hope that this makes sense. Thanks guys!
startDate = ;// get Start Date from UI Convert it to date format using new Date();
endDate = ;// get End Date from UI Convert it to date format using new Date();
MyCollection.find({
leaves_start: { $lte: endDate}, // start Less and endDate
leaves_end: { $gte: startDate } // end greater than StartDate
});
if the startDate and endDate is same you get all the records for that date , else it will be date Range.
You'd do it like this
MyCollection.find({
leaves_start: { $lte: new Date },
leaves_end: { $gte: new Date }
});
I'm not sure if this will be helpful, but here's the code that I came up with:
THE RECORDS
METHOD:
//monthyear = "10-2015"
//numOfDays = 31
getTowerLeaveData_LV: function(monthyear, numOfDays,tower, userid, username) {
var selectedMonthYear = monthyear.split("-");
var tempArr = new Array();
var reArr = new Array()
tempArr.push(username)
reArr.push(username);
LeavesCollection.find({associate_tower: {$in: tower}, leaves_approval_status: {$ne: 'Rejected'}, user_id: userid},{sort:{leaves_timestamp :-1}},{fields: {_id:1,user_id:1,associate_id:1, associate_fullname:1,leaves_type:1,leaves_start:1,leaves_end:1, leaves_days:1}}).forEach(
function(leaver) {
for(var a=1; a!=numOfDays+1; a++) {
var dateActive = selectedMonthYear[0] + "/" + a.toString() + "/" + selectedMonthYear[1];
var res = dateCheck(leaver.leaves_start, leaver.leaves_end,dateActive);
if(res == true) {
tempArr.splice(a, 0,[leaver.leaves_approval_status,leaver.leaves_type,leaver._id,leaver.associate_fullname,a]);
}
}
});
for(var a=1; a!=numOfDays+1; a++) {
var temp = findKey(tempArr,a);
if(temp != false) {
reArr.push(tempArr[temp]);
} else {
reArr.push('null')
}
}
return reArr;
},
MISC JS FUNCTIONS:
function dateCheck(from,to,check) {
var fDate,lDate,cDate;
fDate = Date.parse(from);
lDate = Date.parse(to);
cDate = Date.parse(check);
if((cDate <= lDate && cDate >= fDate)) {
return true;
}
return false;
}
function findKey(array, search) {
var theIndex = false;
for (var i = 0; i < array.length; i++) {
if (array[i].indexOf(search) > -1) {
theIndex = i;
break;
}
}
return(theIndex);
}
OUTPUT IN ARRAY:
EXPLANATION OF OUTPUT:
The items after the Name in the array is equal to the value of numOfDays(which is dates). If the program find a match date to the range between "leaves_start" and "leaves_end", it will return the array data from mongodb, if not, it will return "null".
I want to sort an array in ascending order. The dates are in string format
["09/06/2015", "25/06/2015", "22/06/2015", "25/07/2015", "18/05/2015"]
Even need a function to check whether these dates are in continuous form:
eg - Valid - ["09/06/2015", "10/06/2015", "11/06/2015"]
Invalid - ["09/06/2015", "25/06/2015", "22/06/2015", "25/07/2015"]
Example code:
function sequentialDates(dates){
var temp_date_array = [];
$.each(dates, function( index, date ) {
//var date_flag = Date.parse(date);
temp_date_array.push(date);
});
console.log(temp_date_array);
var last;
for (var i = 0, l = temp_date_array.length; i < l; i++) {
var cur = new Date();
cur.setTime(temp_date_array[i]);
last = last || cur;
//console.log(last+' '+cur);
if (isNewSequence(cur, last)) {
console.log("Not Sequence");
}
}
//return dates;
}
function isNewSequence(a, b) {
if (a - b > (24 * 60 * 60 * 1000))
return true;
return false;
}
The Simple Solution
There is no need to convert Strings to Dates or use RegExp.
The simple solution is to use the Array.sort() method. The sort function sets the date format to YYYYMMDD and then compares the string value. Assumes date input is in format DD/MM/YYYY.
data.sort(function(a,b) {
a = a.split('/').reverse().join('');
b = b.split('/').reverse().join('');
return a > b ? 1 : a < b ? -1 : 0;
// return a.localeCompare(b); // <-- alternative
});
Update:
A helpful comment suggested using localeCompare() to simplify the sort function. This alternative is shown in the above code snippet.
Run Snippet to Test
<!doctype html>
<html>
<body style="font-family: monospace">
<ol id="stdout"></ol>
<script>
var data = ["09/06/2015", "25/06/2015", "22/06/2015", "25/07/2015", "18/05/2015"];
data.sort(function(a,b) {
a = a.split('/').reverse().join('');
b = b.split('/').reverse().join('');
return a > b ? 1 : a < b ? -1 : 0;
// return a.localeCompare(b); // <-- alternative
});
for(var i=0; i<data.length; i++)
stdout.innerHTML += '<li>' + data[i];
</script>
</body>
</html>
You will need to convert your strings to dates, and compare those dates, if you want to sort them. You can make use of the parameter that the sort method accepts, in order to achieve this:
var dateStrings = ["09/06/2015", "25/06/2015", "22/06/2015", "25/07/2015", "18/05/2015"];
var sortedStrings = dateStrings.sort(function(a,b) {
var aComps = a.split("/");
var bComps = b.split("/");
var aDate = new Date(aComps[2], aComps[1], aComps[0]);
var bDate = new Date(bComps[2], bComps[1], bComps[0]);
return aDate.getTime() - bDate.getTime();
});
In order to reduce code redundancy, and to handle different date formats, you can add an additional function that will create the comparator needed by the sort method:
function createSorter(dateParser) {
return function(a, b) {
var aDate = dateParser(a);
var bDate = dateParser(b);
return aDate.getTime() - bDate.getTime();
};
}
dateStrings.sort(createSorter(function(dateString) {
var comps = dateString.split("/");
return new Date(comps[2], comps[1], comps[0]);
}));
You can then use different date formatters by passing different functions to the createSorter call.
As for your second question, you can create an (sorted) array of dates from your strings, and perform your logic on that array:
function myDateParser(dateString) {
var comps = dateString.split("/");
return new Date(comps[2], comps[1], comps[0]);
}
var sortedDates = dateStrings.map(myDateParser).sort();
You can walk through the sortedDates array and if you find two non-consecutive dates, then you have dates with gaps between them.
var dateRE = /^(\d{2})[\/\- ](\d{2})[\/\- ](\d{4})/;
function dmyOrdA(a, b){
a = a.replace(dateRE,"$3$2$1");
b = b.replace(dateRE,"$3$2$1");
if (a>b) return 1;
if (a <b) return -1;
return 0; }
function dmyOrdD(a, b){
a = a.replace(dateRE,"$3$2$1");
b = b.replace(dateRE,"$3$2$1");
if (a>b) return -1;
if (a <b) return 1;
return 0; }
function mdyOrdA(a, b){
a = a.replace(dateRE,"$3$1$2");
b = b.replace(dateRE,"$3$1$2");
if (a>b) return 1;
if (a <b) return -1;
return 0; }
function mdyOrdD(a, b){
a = a.replace(dateRE,"$3$1$2");
b = b.replace(dateRE,"$3$1$2");
if (a>b) return -1;
if (a <b) return 1;
return 0; }
dateArray = new Array("09/06/2015", "25/06/2015", "22/06/2015", "25/07/2015", "18/05/2015");
var c = dateArray.sort( dmyOrdA );
console.log(c);
To sort your date string ascendingly without alteration to its value, try this:
var T = ["09/06/2015", "25/06/2015", "22/06/2015", "25/07/2015", "18/05/2015"];
var sortedT = T.sort(s1,s2){
var sdate1 = s1.split('/');
var sdate2 = s2.split('/');
var date1 = s1[1]+'/'+s1[0]+'/'+s1[2];
var date2 = s2[1]+'/'+s2[0]+'/'+s2[2];
if (Date.parse(date1) > Date.parse(date2)) return 1;
else if (Date.parse(date1) < Date.parse(date2) return -1;
else return 0;
}
The resultant array sortedT should be a sorted array of date string.
NOTE:
Your date format is stored in dd/mm/yyyy but the standard date format of JavaScript is mm/dd/yyyy. Thus, in order to parse this string to Date without using external date format library, the date string is therefore needed to be converted for compatibility during sort.
I've got a startdate and enddate from inputs. And I need to put all the dates from the startdate until the enddate into the database. Therefore I need to make a loop like this:
FOR i = startdate; i <= enddate; i + 1 day
{
here i use the date
}
How do I make such a loop with dates from input boxes?
I get 'invalid date' if I try to do this:
var endDate = new Date($("#enddate").val());
And I can't use the endDate.getTime() like I need as you said in the answer, if I do it like this.
var endDate = $("#enddate").val());
var endDateTime = endDate.getTime();
So basically: How can I convert the input to a date? The input of enddate is like this: dd/mm/yyyy.
No it's not an SQL question, I need to do this is javascript because I need to check the dates first.
Thank you for helping me out ;)
Would a loop like this work?:
var current_date = new Date("01/13/2013");
var end_date = new Date("01/20/2013");
var end_date_time = end_date.getTime();
while (current_date.getTime() < end_date_time) {
console.log(current_date);
current_date.setDate(current_date.getDate()+1);
}
http://jsfiddle.net/Sn6Ws/
Depending on the format of your textboxes' values, you can set it up like this:
$(document).ready(function () {
$("#btn").on("click", function () {
dateLooper(function (cur, end) {
console.log("Current date: " + cur.toString() + ", End Date: " + end.toString());
});
});
});
function dateLooper(callback) {
var start_date_text = document.getElementById("start_date").value;
var end_date_text = document.getElementById("end_date").value;
var current_date = new Date(start_date_text);
var end_date = new Date(end_date_text);
var end_date_time = end_date.getTime();
while (current_date.getTime() < end_date_time) {
//console.log(current_date);
callback.call(this, current_date, end_date);
current_date.setDate(current_date.getDate()+1);
}
}
http://jsfiddle.net/Sn6Ws/1/
Per your comments that explain the date are in the format "dd/mm/yyyy", you could use something like this:
var start_date_text = document.getElementById("start_date").value;
var start_split = start_date_text.split("/");
if (start_split.length != 3) {
return false;
}
start_date_text = start_split[1] + "/" + start_split[0] + "/" + start_split[2];
var end_date_text = document.getElementById("end_date").value;
var end_split = end_date_text.split("/");
if (end_split.length != 3) {
return false;
}
end_date_text = end_split[1] + "/" + end_split[0] + "/" + end_split[2];
to get the dates in the right format before passing them to new Date. Here's an updated jsFiddle that demonstrates it:
http://jsfiddle.net/Sn6Ws/4/
Of course, be careful that if the dates don't come in with the specified format (in case users can type this in or something), the code will most likely throw an error. You can obviously put more checks in to make sure certain things set before proceeding with certain operations (like making sure each item is a number/integer, making sure the days are in the range 1 to 31, etc.). So for that reason, you may want to go the route of regular expressions. At least with regular expressions, you can specify a specific pattern and know whether it matches perfectly or not, and immediately get the values you need to build a date.
Using regular expressions, here's an example that isn't complete but should hopefully help:
function dateLooper(callback) {
var re = /^(\d{1,2})\/(\d{1,2})\/(\d{4})$/;
var start_date_text = document.getElementById("start_date").value;
var start_match = re.exec(start_date_text);
if (start_match) {
var valid = true;
// Set `valid` variable based on the following
// Validate start_match[1] is valid day
// Validate start_match[2] is valid month
// Validate start_match[3] is valid year
if (valid) {
start_date_text = combineDate(start_match);
} else {
return false;
}
} else {
return false;
}
var end_date_text = document.getElementById("end_date").value;
var end_match = re.exec(end_date_text);
if (end_match) {
var valid = true;
// Set `valid` variable based on the following
// Validate end_match[1] is valid day
// Validate end_match[2] is valid month
// Validate end_match[3] is valid year
if (valid) {
end_date_text = combineDate(end_match);
} else {
return false;
}
} else {
return false;
}
var current_date = new Date(start_date_text);
var end_date = new Date(end_date_text);
var end_date_time = end_date.getTime();
var days_spent = 0;
while (current_date.getTime() < end_date_time) {
days_spent++;
callback.call(this, current_date, end_date, days_spent);
current_date.setDate(current_date.getDate()+1);
}
return days_spent;
}
function combineDate(re_match) {
return re_match[2] + "/" + re_match[1] + "/" + re_match[3];
}
http://jsfiddle.net/Sn6Ws/6/