Checking the order of dates in an object - javascript

I am trying to make sure the order of dates entered in an object are in a logical order. Here is my code:
function checkDates(pet) {
const dates = [
pet.birthDate,
pet.saleDate,
pet.acquisitionDate,
pet.deathDate
].filter( (date) => {
// filter out undefined items
return date;
});
// list of dates in their chronological order
const sortedDates = dates.slice(0).sort();
const inOrder = dates.every( (date, i) => {
// check to make sure entered date is the same as the chronological date
return date === sortedDates[i];
});
if (!inOrder) {
throw new ValidationError('The dates are in an illogical order');
}
}
The problem is that saleDate and acquisitionDate do not need to be in that order (as defined in the dates array) - they just need to be more than birthDate and less than deathDate. The different dates are not required, for example, the pet object that gets passed through my look like this:
const pet = {
name: "Sam",
birthDate: "2017-01-01",
acquisitionDate: "2017-02-01",
saleDate: "2017-03-01"
}
Further clarification: If present, birthDate must always come first, and deathDate must always come last. Sale and acquisition must be between birth and death date (if they are present), otherwise, it doesn't matter if sale comes before acquisition or vice-versa.

You are on the right path, but sorting isn't necessarily required:
function checkDates(pet) {
const dates = [
pet.birthDate,
pet.saleDate,
pet.acquisitionDate,
pet.deathDate
].filter(date => date);
const inOrder =
(pet.birthDate ? dates.every(date => date >= pet.birthDate) : true) &&
(pet.deathDate ? dates.every(date => date <= pet.deathDate) : true)
if (!inOrder) {
throw new ValidationError('The dates are in an illogical order');
}
}

You could just iterate the given array, without sorting, becaue all dates have to be in order.
function check({ birthDate, acquisitionDate, saleDate, deathDate }) {
return [birthDate, acquisitionDate, saleDate, deathDate]
.filter(Boolean)
.every((a, i, aa) => !i || aa[i - 1] <= a);
}
console.log(check({ name: "Sam", birthDate: "2017-01-01", acquisitionDate: "2017-02-01", saleDate: "2017-03-01" }));
console.log(check({ name: "Sam", birthDate: "2018-01-01", acquisitionDate: "2017-02-01", saleDate: "2017-03-01" }));

Assuming the deathDate is the only optional property here, but it appears it could be done in two checks:
birthDate is less than the minimum of acquisitionDate/saleDate
if deathDate, deathDate is greater than the maximum of acquisitionDate/saleDate
Something along these lines:
function checkDates(pet) {
const inOrder = (
pet.birthDate < Math.min.apply(null, [pet.acquisitionDate, pet.saleDate]) &&
pet.deathDate ? pet.deathDate > Math.max.apply(null, [pet.acquisitionDate, pet.saleDate]) : true
);
if (!inOrder) {
throw new ValidationError('The dates are in an illogical order')
}
return true;
}
const pet = {
birthDate: "2017-01-01",
acquisitionDate: "2017-02-01",
saleDate: "2017-03-01"
};
console.log(checkDates(pet));
If other properties are optional that would change things a bit but not too drastically.

You are saying that the order of both saleDate and acquisitionDate is not important they just need to be higher than birthDate and lower than deathDate, in that case you can simplify your function to do only these four checks:
function checkDates(pet) {
var birthDate = new Date(pet.birthDate);
var saleDate = new Date(pet.saleDate);
var acquisitionDate = new Date(pet.acquisitionDate);
var deathDate = pet.deathDate ? new Date(pet.deathDate) : Infinity;
var inOrder = (birthDate < saleDate) && (birthDate < acquisitionDate) && (saleDate < deathDate) && (acquisitionDate < deathDate);
if (!inOrder) {
throw new ValidationError('The dates are in an illogical order');
}
}
There's no need for using an array and for the sorting and the looping operations, it's really useless.
Demo:
function checkDates(pet) {
var birthDate = new Date(pet.birthDate);
var saleDate = new Date(pet.saleDate);
var acquisitionDate = new Date(pet.acquisitionDate);
var deathDate = pet.deathDate ? new Date(pet.deathDate) : Infinity;
var inOrder = (birthDate < saleDate) && (birthDate < acquisitionDate) && (saleDate < deathDate) && (acquisitionDate < deathDate);
if (!inOrder) {
throw new ValidationError('The dates are in an illogical order');
}
}
console.log(checkDates({
name: "Sam",
birthDate: "2018-01-01",
acquisitionDate: "2017-02-01",
saleDate: "2017-03-01"
}));

Related

Elements in the date array update automatically

I'm trying to find week days between first date and second date (exclusive first and second). In the array that contains the weekday dates, the values get increment after line 1 in executed, which is unexpected.
private getListOfWeekDaysBetweenTwoDates(
startDate: Date,
endDate: Date
): Date[] {
const weekdaysList = [];
let tempDate = this.addDaystoGivenDate(startDate, 1);
while (tempDate < endDate) {
if (this.isWeekDay(tempDate)) {
weekdaysList.push(tempDate);
}
//line 1
tempDate = this.addDaystoGivenDate(tempDate, 1);
}
return weekdaysList;
}
private addDaystoGivenDate(date: Date, numberOfDays: number): Date {
return new Date(date.setUTCDate(date.getUTCDate() + numberOfDays));
}
private isWeekDay(day: Date): boolean {
if (day.getUTCDay() >= 1 && day.getUTCDay() <= 5) {
return true;
}
return false;
}
How do I stop array values changing?
Isolating the problem, you're changing the date after inserting it to the array, but what you're inserting is a reference to the date:
let d = new Date()
d.setUTCDate(1)
const arr = []
arr.push(d)
console.log(arr)
d.setUTCDate(10)
console.log(arr) //date in arr changes from 1 to 10
That's because you're calling date.setUTCDate() over tempDate.
There is more than one way to solve it, but for example you could store not the reference to tempDate but a completely new Date object:
weekdaysList.push(tempDate); => weekdaysList.push(new Date(tempDate));
In the simplified example:
let d = new Date()
const arr = []
d.setUTCDate(1)
arr.push(new Date(d))
console.log(arr)
d.setUTCDate(10)
console.log(arr) //date in arr keeps 1

How to get the oldest person in this array

I'm practicing my javascript and I've come across the following array.
const people = [
{
name: 'Carly',
yearOfBirth: 2018,
},
{
name: 'Ray',
yearOfBirth: 1962,
yearOfDeath: 2011
},
{
name: 'Jane',
yearOfBirth: 1912,
yearOfDeath: 1941
},
]
i'm trying to find the oldest person in the array but I keep getting the wrong person.here's my code
let findTheOldest = function(people) {
const oldest = people.sort((a,b) => (a.yearOfDeath - a.yearOfBirth) > (b.yearOfDeath - b.yearOfBirth) ? -1 : 1);
return oldest[0];
}
so it keeps saying that 'Carly' is the oldest person rather than 'Ray'? How would I go about it? note that 'Carly' has no yearOfDeath and therefore she is still alive.
You can use reduce, and use the current year for people without a death date:
const people = [{name:"Carly",yearOfBirth:2018},{name:"Ray",yearOfBirth:1962,yearOfDeath:2011},{name:"Jane",yearOfBirth:1912,yearOfDeath:1941}];
const findTheOldest = function(people) {
const thisYear = new Date().getFullYear();
return people.reduce((res, person) => {
const age = (person.yearOfDeath || thisYear) - person.yearOfBirth;
return age > res.age ? { person, age } : res;
}, { person: null, age: 0 }).person;
}
console.log(findTheOldest(people)); // Ray
As an Engineer, most proofs I study at college assume something and we work it out, then at the end of the proof, Maths will tell you if your assumption was right.
We'll assume we have a function called getAge(person) that has a signature as follows.
// this performance improvement of storing the year was suggested by #blex
let currentYear = new Date().getFullYear();
let getAge = (person) => {
return (person.yearOfDeath ? person.yearOfDeath : currentYear) - person.yearOfBirth
};
Basically, if the person doesn't have a .yearOfDeath, he's still alive and the current year 2020 at the time of writing this answer.
and we have a getOldest(people) that has a signature as follows.
let getOldest = people => {
/** Keep in mind that people can be mutated and you
need to avoid this here
*/
// An assumption. It can be right or wrong.
let oldest_person = people[0];
// The first method (slice) returns a shallow copy
// the second one (splice) removes the oldest_person
// removing it makes the loop count decrease by one. Nothing else.
// we don't need a deep copy, we won't alter the people.
people = (people.slice()).splice(1);
// You could save the getAge(oldest_person) in a variable
// instead of computing it each time
// I wanted this to be as readable as possible.
for (let person of people){
if (getAge(person) > getAge(oldest_person)){
// Congrats! we have a new older person!
oldest_person = person;
}
}
return oldest_person;
};
This has a worst-case time complexity of o(n).
For illustration, let's benchmark this.
let people = []
let init = () => {
let randomInteger = (min, max) => {
// return random integer between min, max, found this on stackoverflow
return Math.floor(Math.random() * (max - min + 1)) + min;
}
for (let i = 0; i < 10000000; i++){ // 10m person
let dateOfBirth = parseInt('19' + randomInteger(10,99));
let dateOfDeath = parseInt('20' + randomInteger(10, 99));
let person = {
name: `person_${i}`,
dateOfBirth, // same as dateOfBirth: dateOfBirth,
dateOfDeath, // same logic
}
people.push(person); // add it to people
}
}
init();
start = performance.now(); // time in millisecs
getOldest(people);
end = performance.now(); // time in millisecs after getting the oldest person
console.log((end - start ) * Math.pow(10, -3)) // time elapsed is around 0.2 secs.
To use sort to find the oldest, you need to include a default specifying the current year for people without a yearOfDeath. Below I've done this in a helper function called "age".
Using sort if your only purpose is to find a maximum can be inefficient though, particularly if you're dealing with a lot of data: try using reduce, as per other answer.
const people = [
{
name: "Carly",
yearOfBirth: 2018,
},
{
name: "Ray",
yearOfBirth: 1962,
yearOfDeath: 2011,
},
{
name: "Jane",
yearOfBirth: 1912,
yearOfDeath: 1941,
},
];
let findTheOldest = function (people) {
const age = (x) => (x.yearOfDeath || new Date().getFullYear()) - x.yearOfBirth;
const oldest = people.sort((a, b) =>
age(a) > age(b) ? -1 : 1
);
return oldest[0];
};
console.log(findTheOldest(people));

how to sort string data by date? [duplicate]

Say I have an array of a few objects:
var array = [{id: 1, date: Mar 12 2012 10:00:00 AM}, {id: 2, date: Mar 8 2012 08:00:00 AM}];
How can I sort this array by the date element in order from the date closest to the current date and time down? Keep in mind that the array may have many objects, but for the sake of simplicity I used 2.
Would I use the sort function and a custom comparator?
Simplest Answer
array.sort(function(a,b){
// Turn your strings into dates, and then subtract them
// to get a value that is either negative, positive, or zero.
return new Date(b.date) - new Date(a.date);
});
More Generic Answer
array.sort(function(o1,o2){
if (sort_o1_before_o2) return -1;
else if(sort_o1_after_o2) return 1;
else return 0;
});
Or more tersely:
array.sort(function(o1,o2){
return sort_o1_before_o2 ? -1 : sort_o1_after_o2 ? 1 : 0;
});
Generic, Powerful Answer
Define a custom non-enumerable sortBy function using a Schwartzian transform on all arrays :
(function(){
if (typeof Object.defineProperty === 'function'){
try{Object.defineProperty(Array.prototype,'sortBy',{value:sb}); }catch(e){}
}
if (!Array.prototype.sortBy) Array.prototype.sortBy = sb;
function sb(f){
for (var i=this.length;i;){
var o = this[--i];
this[i] = [].concat(f.call(o,o,i),o);
}
this.sort(function(a,b){
for (var i=0,len=a.length;i<len;++i){
if (a[i]!=b[i]) return a[i]<b[i]?-1:1;
}
return 0;
});
for (var i=this.length;i;){
this[--i]=this[i][this[i].length-1];
}
return this;
}
})();
Use it like so:
array.sortBy(function(o){ return o.date });
If your date is not directly comparable, make a comparable date out of it, e.g.
array.sortBy(function(o){ return new Date( o.date ) });
You can also use this to sort by multiple criteria if you return an array of values:
// Sort by date, then score (reversed), then name
array.sortBy(function(o){ return [ o.date, -o.score, o.name ] };
See http://phrogz.net/JS/Array.prototype.sortBy.js for more details.
#Phrogz answers are both great, but here is a great, more concise answer:
array.sort(function(a,b){return a.getTime() - b.getTime()});
Using the arrow function way
array.sort((a,b)=>a.getTime()-b.getTime());
found here: Sort date in Javascript
After correcting the JSON this should work for you now:
var array = [{id: 1, date:'Mar 12 2012 10:00:00 AM'}, {id: 2, date:'Mar 8 2012 08:00:00 AM'}];
array.sort(function(a, b) {
var c = new Date(a.date);
var d = new Date(b.date);
return c-d;
});
Your data needs some corrections:
var array = [{id: 1, date: "Mar 12 2012 10:00:00 AM"},{id: 2, date: "Mar 28 2012 08:00:00 AM"}];
After correcting the data, you can use this piece of code:
function sortFunction(a,b){
var dateA = new Date(a.date).getTime();
var dateB = new Date(b.date).getTime();
return dateA > dateB ? 1 : -1;
};
var array = [{id: 1, date: "Mar 12 2012 10:00:00 AM"},{id: 2, date: "Mar 28 2012 08:00:00 AM"}];
array.sort(sortFunction);​
Above answers are all good 😊, here is my implementation of sorting date in ES6 way, I'm using Date.parse (is global Date object) this will convert string representation of Date to number of milliseconds. Instead of instantiating new Date object every time.
var array = ["2021-08-10T07:24:30.087+0000" , "2021-09-30T07:24:30.087+0000", "2021-10-13T07:24:30.087+0000"];
// sorting with latest date
array.sort((a,b) => Date.parse(b) - Date.parse(a))
I recommend GitHub: Array sortBy - a best implementation of sortBy method which uses the Schwartzian transform
But for now we are going to try this approach Gist: sortBy-old.js.
Let's create a method to sort arrays being able to arrange objects by some property.
Creating the sorting function
var sortBy = (function () {
var toString = Object.prototype.toString,
// default parser function
parse = function (x) { return x; },
// gets the item to be sorted
getItem = function (x) {
var isObject = x != null && typeof x === "object";
var isProp = isObject && this.prop in x;
return this.parser(isProp ? x[this.prop] : x);
};
/**
* Sorts an array of elements.
*
* #param {Array} array: the collection to sort
* #param {Object} cfg: the configuration options
* #property {String} cfg.prop: property name (if it is an Array of objects)
* #property {Boolean} cfg.desc: determines whether the sort is descending
* #property {Function} cfg.parser: function to parse the items to expected type
* #return {Array}
*/
return function sortby (array, cfg) {
if (!(array instanceof Array && array.length)) return [];
if (toString.call(cfg) !== "[object Object]") cfg = {};
if (typeof cfg.parser !== "function") cfg.parser = parse;
cfg.desc = !!cfg.desc ? -1 : 1;
return array.sort(function (a, b) {
a = getItem.call(cfg, a);
b = getItem.call(cfg, b);
return cfg.desc * (a < b ? -1 : +(a > b));
});
};
}());
Setting unsorted data
var data = [
{date: "2011-11-14T17:25:45Z", quantity: 2, total: 200, tip: 0, type: "cash"},
{date: "2011-11-14T16:28:54Z", quantity: 1, total: 300, tip: 200, type: "visa"},
{date: "2011-11-14T16:30:43Z", quantity: 2, total: 90, tip: 0, type: "tab"},
{date: "2011-11-14T17:22:59Z", quantity: 2, total: 90, tip: 0, type: "tab"},
{date: "2011-11-14T16:53:41Z", quantity: 2, total: 90, tip: 0, type: "tab"},
{date: "2011-11-14T16:48:46Z", quantity: 2, total: 90, tip: 0, type: "tab"},
{date: "2011-11-31T17:29:52Z", quantity: 1, total: 200, tip: 100, type: "visa"},
{date: "2011-11-01T16:17:54Z", quantity: 2, total: 190, tip: 100, type: "tab"},
{date: "2011-11-14T16:58:03Z", quantity: 2, total: 90, tip: 0, type: "tab"},
{date: "2011-11-14T16:20:19Z", quantity: 2, total: 190, tip: 100, type: "tab"},
{date: "2011-11-14T17:07:21Z", quantity: 2, total: 90, tip: 0, type: "tab"},
{date: "2011-11-14T16:54:06Z", quantity: 1, total: 100, tip: 0, type: "cash"}
];
Using it
Finally, we arrange the array, by "date" property as string
//sort the object by a property (ascending)
//sorting takes into account uppercase and lowercase
sortBy(data, { prop: "date" });
If you want to ignore letter case, set the "parser" callback:
//sort the object by a property (descending)
//sorting ignores uppercase and lowercase
sortBy(data, {
prop: "date",
desc: true,
parser: function (item) {
//ignore case sensitive
return item.toUpperCase();
}
});
If you want to treat the "date" field as Date type:
//sort the object by a property (ascending)
//sorting parses each item to Date type
sortBy(data, {
prop: "date",
parser: function (item) {
return new Date(item);
}
});
Here you can play with the above example:
jsbin.com/lesebi
This should do when your date is in this format (dd/mm/yyyy).
sortByDate(arr) {
arr.sort(function(a,b){
return Number(new Date(a.readableDate)) - Number(new Date(b.readableDate));
});
return arr;
}
Then call sortByDate(myArr);
arr is an array of object and each object has date_prop which is a date. You can sort it in descending/decreasing order like this
arr = arr.sort(function (a, b) {
var dateA = new Date(a.date_prop).getTime();
var dateB = new Date(b.date_prop).getTime();
return dateA < dateB ? 1 : -1; // ? -1 : 1 for ascending/increasing order
});
You could use sortBy in underscore js.
http://underscorejs.org/#sortBy
Sample:
var log = [{date: '2016-01-16T05:23:38+00:00', other: 'sample'},
{date: '2016-01-13T05:23:38+00:00',other: 'sample'},
{date: '2016-01-15T11:23:38+00:00', other: 'sample'}];
console.log(_.sortBy(log, 'date'));
With ES6 arrow functions, you can further write just one line of concise code (excluding variable declaration).
Eg.:
var isDescending = true; //set to false for ascending
console.log(["8/2/2020","8/1/2020","8/13/2020", "8/2/2020"].sort((a,b) => isDescending ? new Date(b).getTime() - new Date(a).getTime() : new Date(a).getTime() - new Date(b).getTime()));
Since time does not exists with the above dates, the Date object will consider following default time for sorting:
00:00:00
The code will work for both ascending and descending sort.
Just change the value of isDescending variable as required.
Strings with dates are comparable in JavaScript (if they are syntactically the same), e.g.:
'2020-12-01' < '2020-12-02' == true
This means you can use this expression in a custom sort function:
var arr = [{id:1, date:'2020-12-01'}, {id:1, date:'2020-12-15'}, {id:1, date:'2020-12-12'}]
function sortByDate(a, b) {
if (a.date < b.date) {
return 1;
}
if (a.date > b.date) {
return -1;
}
return 0;
}
const sorted = arr.sort(sortByDate);
console.log(sorted);
I'm going to add this here, as some uses may not be able to work out how to invert this sorting method.
To sort by 'coming up', we can simply swap a & b, like so:
your_array.sort ( (a, b) => {
return new Date(a.DateTime) - new Date(b.DateTime);
});
Notice that a is now on the left hand side, and b is on the right, :D!
i was able to achieve sorting using below lines:
array.sort(function(a, b)
{
if (a.DueDate > b.DueDate) return 1;
if (a.DueDate < b.DueDate) return -1;
})
I personally use following approach to sort dates.
let array = ["July 11, 1960", "February 1, 1974", "July 11, 1615", "October 18, 1851", "November 12, 1995"];
array.sort(function(date1, date2) {
date1 = new Date(date1);
date2 = new Date(date2);
if (date1 > date2) return 1;
if (date1 < date2) return -1;
})
Adding absolute will give better results
var datesArray =[
{"some":"data1","date": "2018-06-30T13:40:31.493Z"},
{"some":"data2","date": "2018-07-04T13:40:31.493Z"},
{"some":"data3","date": "2018-06-27T13:40:54.394Z"}
]
var sortedJsObjects = datesArray.sort(function(a,b){
return Math.abs(new Date(a.date) - new Date(b.date))
});
Here is the shortest way to solve your problem.
var array = [{id: 1, date: 'Mar 12 2012 10:00:00 AM'}, {id: 2, date: 'Mar 8 2012 08:00:00 AM'}];
var sortedArray = array.sort((a,b) => Date.parse(new Date(a.date)) - Date.parse(new Date(b.date)));
Thank you Ganesh Sanap. sorting items by date field from old to new. Use it
myArray = [{transport: "Air",
load: "Vatican Vaticano",
created: "01/31/2020"},
{transport: "Air",
load: "Paris",
created: "01/30/2020"}]
myAarray.sort(function(a, b) {
var c = new Date(a.created);
var d = new Date(b.created);
return c-d;
});
Simple one line solution for me to sort dates :
sort((a, b) => (a < b ? 1 : -1))
["12 Jan 2018" , "1 Dec 2018", "04 May 2018"].sort(function(a,b) {
return new Date(a).getTime() - new Date(b).getTime()
})
For anyone who is wanting to sort by date (UK format), I used the following:
//Sort by day, then month, then year
for(i=0;i<=2; i++){
dataCourses.sort(function(a, b){
a = a.lastAccessed.split("/");
b = b.lastAccessed.split("/");
return a[i]>b[i] ? -1 : a[i]<b[i] ? 1 : 0;
});
}
I have just taken the Schwartzian transform depicted above and made as function. It takes an array, the sorting function and a boolean as input:
function schwartzianSort(array,f,asc){
for (var i=array.length;i;){
var o = array[--i];
array[i] = [].concat(f.call(o,o,i),o);
}
array.sort(function(a,b){
for (var i=0,len=a.length;i<len;++i){
if (a[i]!=b[i]) return a[i]<b[i]?asc?-1:1:1;
}
return 0;
});
for (var i=array.length;i;){
array[--i]=array[i][array[i].length-1];
}
return array;
}
function schwartzianSort(array, f, asc) {
for (var i = array.length; i;) {
var o = array[--i];
array[i] = [].concat(f.call(o, o, i), o);
}
array.sort(function(a, b) {
for (var i = 0, len = a.length; i < len; ++i) {
if (a[i] != b[i]) return a[i] < b[i] ? asc ? -1 : 1 : 1;
}
return 0;
});
for (var i = array.length; i;) {
array[--i] = array[i][array[i].length - 1];
}
return array;
}
arr = []
arr.push({
date: new Date(1494434112806)
})
arr.push({
date: new Date(1494434118181)
})
arr.push({
date: new Date(1494434127341)
})
console.log(JSON.stringify(arr));
arr = schwartzianSort(arr, function(o) {
return o.date
}, false)
console.log("DESC", JSON.stringify(arr));
arr = schwartzianSort(arr, function(o) {
return o.date
}, true)
console.log("ASC", JSON.stringify(arr));
If like me you have an array with dates formatted like YYYY[-MM[-DD]] where you'd like to order more specific dates before less specific ones, I came up with this handy function:
function sortByDateSpecificity(a, b) {
const aLength = a.date.length
const bLength = b.date.length
const aDate = a.date + (aLength < 10 ? '-12-31'.slice(-10 + aLength) : '')
const bDate = b.date + (bLength < 10 ? '-12-31'.slice(-10 + bLength) : '')
return new Date(aDate) - new Date(bDate)
}
Thanks for those brilliant answers on top. I have thought a slightly complicated answer. Just for those who want to compare different answers.
const data = [
'2-2018', '1-2018',
'3-2018', '4-2018',
'1-2019', '2-2019',
'3-2019', '4-2019',
'1-2020', '3-2020',
'4-2020', '1-2021'
]
let eachYearUniqueMonth = data.reduce((acc, elem) => {
const uniqueDate = Number(elem.match(/(\d+)\-(\d+)/)[1])
const uniqueYear = Number(elem.match(/(\d+)\-(\d+)/)[2])
if (acc[uniqueYear] === undefined) {
acc[uniqueYear] = []
} else{
if (acc[uniqueYear] && !acc[uniqueYear].includes(uniqueDate)) {
acc[uniqueYear].push(uniqueDate)
}
}
return acc;
}, {})
let group = Object.keys(eachYearUniqueMonth).reduce((acc,uniqueYear)=>{
eachYearUniqueMonth[uniqueYear].forEach(uniqueMonth=>{
acc.push(`${uniqueYear}-${uniqueMonth}`)
})
return acc;
},[])
console.log(group); //["2018-1", "2018-3", "2018-4", "2019-2", "2019-3", "2019-4", "2020-3", "2020-4"]
I have an array of objects in which key 'time' contains the date in ISO format
Example - 2021-12-24T11:02:20.370705
arr.sort(function(a,b){return a.time > b.time ? 1 : a.time < b.time ? -1 : 0 });
Above worked for me like a charm!
If you are into MongoDB, one of the solutions is:
db.collection.find({}).sort("your date field");
For example:
db.collection.find({}).sort("createdAt");

How to merge properties inside object into one property?

I have object of orders
{
someUserData,
createdAt: 2019-11-05T18:32:25.199+00:00,
total: 5
}
I want to achieve this kind of data structure:
{
2019: {
0: 5,
1: 100
total: 999
}
}
2019 - year
0,1 etc. - months, total value to the right
total: yearly income
I've tried this:
calculateMonthlyRevenue = () => {
const { orders } = this.state;
const ordersMonthly = orders.map(x =>({
...x,
year: new Date(x.createdAt).getFullYear(),
month: new Date(x.createdAt).getMonth(),
}
));
const sumPerMonth = ordersMonthly.reduce((acc, cur) => {
acc[cur.year] = acc[cur.year] + cur.total || cur.total;
acc[cur.month] = acc[cur.month] + cur.total || cur.total;
return acc;
}, {})
};
acc is giving me
{
10: amount of all Novembers throught history,
2019: I get the total amount, that is good but the data structure is not
what I need.
}
I've tried this:
acc[cur.year][cur.month] = acc[cur.year][cur.month] + cur.total || cur.total;
and this
acc[cur.year[cur.month]] = acc[cur.year[cur.month]] + cur.total || cur.total;
And I still get stuck.
Upper line of codes gives me
9: amount
undefined: amount
The last line of code throws an error (Can not read property undefined of 10)
You could split the ISO 8601 date string for getting year and month and use a default object with total for the year and a default value of zero for the month.
Add to both targets the total from the original object.
var data = [{ someUserData: 'foo', createdAt: '2019-11-05T18:32:25.199+00:00', total: 5 }],
result = data.reduce((r, { createdAt, total }) => {
var [year, month] = createdAt.split('-', 2);
r[year] = r[year] || { total: 0 };
r[year][month -1 ] = (r[year][month - 1] || 0) + total;
r[year].total += total;
return r;
}, {});
console.log(result);

Counting array elements with specific date in javascript

I have an array of Date() objects in javascript and I want to count the number of events on each day.
Here is an example:
What I have is:
Array [ Date 2014-12-04T10:30:20.000Z, Date 2014-12-05T11:04:58.056Z, Date 2014-12-05T11:04:58.056Z, Date 2014-12-05T11:04:58.056Z ]
What I want is:
Array [{date: '2014-12-04', counts: 1}, {date: '2014-12-05', counts: 3}]
Thanks a lot!
Max
Basic answer:
var arr = [], // fill it with array with your data
results = {}, rarr = [], i, date;
for (i=0; i<arr.length; i++) {
// get the date
date = [arr[i].getFullYear(),arr[i].getMonth(),arr[i].getDate()].join("-");
results[date] = results[date] || 0;
results[date]++;
}
// you can always convert it into an array of objects, if you must
for (i in results) {
if (results.hasOwnProperty(i)) {
rarr.push({date:i,counts:results[i]});
}
}
These can be made much easier with lodash functions, and Array.forEach() in ES5
You much better off having a simple object with the keys as the date and the value as the count. I've added a simple pad function that prefixes a zero where the number is a single digit as per your output requirements.
function pad(n) {
return n.toString().length == 1 ? '0' + n : n;
}
function getCount(arr) {
var obj = {};
for (var i = 0, l = arr.length; i < l; i++) {
var thisDate = arr[i];
var day = pad(thisDate.getDate());
var month = pad(thisDate.getMonth() + 1);
var year = thisDate.getFullYear();
var key = [year, day, month].join('-');
obj[key] = obj[key] || 0;
obj[key]++;
}
return obj;
}
getCount(arr); // Object { 2014-04-12: 1, 2014-05-12: 3 }
DEMO
I came across the same issue and found this solution which uses Map()
`
calc = (obj) => {
const orders = []
const dates_map = new Map()
//iterate through all the objects inside the orders array
orders.forEach(order => {
// format and get the date
const date = new Date(order.created_at).toLocaleDateString('en-GB')
//check if the date key exists in the Map() and save it in a temp
const temp = dates_map.get(date) || false
// if it does not exist
if (temp) {
// clone the object
const previous = {...temp}
// increase counter
previous.count += 1
dates_map.set(date, previous)
}else{
//create new object to avoid overwriting
const result = {}
result.count = 1
dates_map.set(date, result)
}
})
console.log(dates_map)
}
And this is the output
Output: Map(3) {
'08/05/2021' => { count: 2 },
'09/05/2021' => { count: 1 },
'11/05/2021' => { count: 2,}
}
`

Categories