convert string to date in mongodb? - javascript

I am using find to get the result then I'm applying Array.prototype.filter in javascript to filter the dates in between 2 given date strings in format dd-mm-yyyy.
let query = {};
req.query.query && (query.name = new RegExp(req.query.query, 'i'));
req.query.gender && (query.gender = new RegExp(`^${req.query.gender}$`, 'i'));
Student.find(query, { roll: 1, name: 1, _id: 0, email: 1, DOB: 1, gender: 1 }, (err, students) => {
if (err) {
next(err);
}
else {
if (req.query.DOB_from && req.query.DOB_to) {
let from = toDate(req.query.DOB_from);
let to = toDate(req.query.DOB_to)
res.send(filterBetweenDates(students, from, to));
}
else {
res.send(students)
}
}
});
/**
* Returns time val in mil secs from a date string in Indian format i.e dd-mm-yyyy
* #param {string} dateStr
*/
function toDate(dateStr) {
let a = dateStr.split('-').map(Number);
let d = new Date(a[2], a[1] - 1, a[0]);
return d.getTime();
}
/**
* Filters the result which matches the date
* #param {Student1[]} students resultant students array
* #param {Number} from time val in millisecs(from)
* #param {Number} to time val in millisecs(from)
*/
function filterBetweenDates(students, from, to) {
return students.filter(({ DOB }) => {
return (from <= toDate(DOB)) && (to >= toDate(DOB));
});
}
The issue I'm facing is that the dates are in dd-mm-yyyy format saved as a string And also the input is in the same format as string. So, I'm first applying other queries and then filtering according to the dates. Is there a way I can do this in the query itself?
Edit:
Sample Collection
[
{
"name": "vib",
"roll": 413,
"email": "abc#example.com",
"DOB": "25-07-1997",
"gender": "Male"
}
{
"name":"abc",
"roll":123,
"email": "abc#xyz.com",
"DOB": "07-11-2000",
"gender": "Female"
}
]

You can use $dateFromString aggregation which change your string DOB to date and then you can $match the date and for changing user date format you can use moment libaray
db.collection.aggregate([
{
"$addFields": {
"date": {
"$dateFromString": {
"dateString": "$DOB"
}
}
}
},
{ "$match": { "date": { "$lte": date, "$gte": date }}}
])

Related

Filter an array of objects with latest date if array contains same date with different timestamp in multiple objects

I have an array of objects and each object has the date. I need to filter the array and get the objects that contains latest date.
[
{
"Id": 25,
"MeasureDate": "2022-08-26T00:01:01.001Z"
},
{
"Id": 26,
"MeasureDate": "2022-08-26T11:10:01.001Z"
},
{
"Id": 27,
"MeasureDate": "2022-08-26T16:12:01.001Z"
},
{
"Id": 30,
"MeasureDate": "2022-08-27T00:08:01.001Z"
},
{
"Id": 31,
"MeasureDate": "2022-08-27T10:20:10.001Z"
}
]
After filtering the array I need the array should look like below
[
{
"Id": 27,
"MeasureDate": "2022-08-26T16:12:01.001Z"
},
{
"Id": 31,
"MeasureDate": "2022-08-27T10:20:10.001Z"
}
]
const dateItems = [
{
"Id": 25,
"MeasureDate": "2022-08-26T00:01:01.001Z"
},
{
"Id": 26,
"MeasureDate": "2022-08-26T11:10:01.001Z"
},
{
"Id": 27,
"MeasureDate": "2022-08-26T16:12:01.001Z"
},
{
"Id": 30,
"MeasureDate": "2022-08-27T00:08:01.001Z"
},
{
"Id": 31,
"MeasureDate": "2022-08-27T10:20:10.001Z"
}
];
// As we loop through your dateItems array we need to keep track of the Latest DateTime for each day
// Probably the easiest way is to create a key on a property for each date and then attach the object
// from your array to that key if it is the first for that date or later than an existing one.
const latestDateTimesByDate = {};
dateItems.forEach( di => {
// Use the date part of the date time as a key/ property name on the latestDateTimesByDate object
let dateKey = di.MeasureDate.substring(0, 10);
// If that date key doesnt exist or the current MeasureDate is gretaer than the recorded one
if( !latestDateTimesByDate[dateKey] || di.MeasureDate > latestDateTimesByDate[dateKey].MeasureDate) {
latestDateTimesByDate[dateKey] = di;
}
});
// if you need it as an array then add each of the date properties to an element of an array
const finalArray = [];
Object.keys(latestDateTimesByDate).forEach( key => finalArray.push(latestDateTimesByDate[key]));
Here's a solution for your probleme :
function similarDates(obj){
date_obj = new Date(obj.MeasureDate);
// Getting only the dates with same year, month, day
let sim_dates = popo.filter((objs) => {
date = new Date(objs.MeasureDate)
return date.toDateString() === date_obj.toDateString()
});
// Returning the similare dates
return sim_dates
}
function filterData(array) {
result = []
while(array.length) {
console.log(array)
var sameElement = similarDates(array[0]);
// removing all the treated elements from the array
array = array.filter( ( el ) => !sameElement.includes(el));
result.push(sameElement.sort((a, b) => new Date(b.MeasureDate) - new Date(a.MeasureDate)).shift());
}
return result;
}

Get items for today and yesterday based off timestamp

I have a json object which is generated using lowdb. Each json entry has a timestamp. I wan't to get all the entry for yesterday, and today based on the timestamp.
The items variable here is just a json object. Here is a sample
{
"items": [
{
"date": 1596131220030,
"item": {
"price": "160,00",
"title": "Cotton Quarter-Zip Sweater"
}
},
{
"date": 1596232321030,
"item": {
"price": "160,00",
"title": "Cotton Quarter-Zip Sweater"
}
}
]
}
I want to get the items from yesterday, and today in this functuin
export async function report(){
try {
const items = db.get('items').value();
return items;
} catch (error) {
console.log(error);
}
}
You can compare with time values for the start of "today" and "yesterday", e.g.
// Return time value for the start of given date, default is today
function getToday(d = new Date()) {
return new Date(+d).setHours(0,0,0,0);
}
// Return time value for the start of day prior to given day, default is today
function getYesterday(d = new Date()) {
let e = new Date(getToday(d));
return e.setDate(e.getDate() - 1);
}
let data = {
"items": [
{"date": 1596085802005, // 30 Jul 2020
"item": "1"
},
{"date": 1596131220030, // 31 Jul 2020
"item": "2"
},
{"date": 1596232321030, // 1 Aug 2020
"item": "3"
}
]
}
// Run as for 1 Aug 2020
let yesterday = getYesterday(new Date(2020,7,1));
let result = data.items.filter(item => item.date >= yesterday);
console.log(result);
Results may vary based on the host timezone offset as the above uses local date values.
You need to parse the date, and compare the difference as follows:
let obj = {
"items": [
{
"date": 1596131220030,
"item": {
"price": "160,00",
"title": "Cotton Quarter-Zip Sweater"
}
},
{
"date": 1596232321030,
"item": {
"price": "160,00",
"title": "Cotton Quarter-Zip Sweater"
}
}
]
};
let list = [];
let items = obj.items;
let today = new Date();
for(let i = 0; i < items.length; i++){
var d = new Date(items[i].date);
var diff = Math.floor((d - today) / (1000 * 60 * 60 * 24));
if(diff == 0 || diff == -1)
list.push(items[i].item);
}
console.log(list);

Count array items by month and year

I am getting dates in json of multiple parcels. the dates usually tells on which date and time that particular parcels was created. So with that date I want to count number of parcels created in each month. I have never done this before and i am not sure what thread of stackoverflow can help me out in this regard. I would very much appreciate any explanation to solve this help or a code reference.
Here is my sample JSON result
[
{
"createdAt": "2019-12-30T04:36:05.001Z"
},
{
"createdAt": "2019-12-06T08:58:23.030Z"
},
{
"createdAt": "2020-01-08T19:00:21.873Z"
},
{
"createdAt": "2020-01-10T14:55:50.781Z"
},
{
"createdAt": "2019-12-21T13:05:09.983Z"
},
{
"createdAt": "2020-01-15T12:10:20.316Z"
},
{
"createdAt": "2020-01-14T06:47:36.078Z"
},
{
"createdAt": "2020-02-15-T06:47:36.078Z"
}
]
I am working with angular so i am getting this data from my service. So now i need to show month wise total number of parcels created.
You could get a part of the ISO 8601 date string as key and count with an object.
var data = [{ createdAt: "2019-12-30T04:36:05.001Z" }, { createdAt: "2019-12-06T08:58:23.030Z" }, { createdAt: "2020-01-08T19:00:21.873Z" }, { createdAt: "2020-01-10T14:55:50.781Z" }, { createdAt: "2019-12-21T13:05:09.983Z" }, { createdAt: "2020-01-15T12:10:20.316Z" }, { createdAt: "2020-01-14T06:47:36.078Z" }, { createdAt: "2020-02-15-T06:47:36.078Z" }],
result = data.reduce((r, { createdAt }) => {
var key = createdAt.slice(0, 7);
r[key] = (r[key] || 0) + 1;
return r;
}, {});
console.log(result);
You can use Array.prototype.reduce() to summarize your records.
const src = [{"createdAt":"2019-12-30T04:36:05.001Z"},{"createdAt":"2019-12-06T08:58:23.030Z"},{"createdAt":"2020-01-08T19:00:21.873Z"},{"createdAt":"2020-01-10T14:55:50.781Z"},{"createdAt":"2019-12-21T13:05:09.983Z"},{"createdAt":"2020-01-15T12:10:20.316Z"},{"createdAt":"2020-01-14T06:47:36.078Z"},{"createdAt":"2020-02-15T06:47:36.078Z"}],
summary = src.reduce((res,{createdAt}) => {
const year = new Date(createdAt).getFullYear(),
month = new Date(createdAt).getMonth()+1
res[`${year}-${month}`] = (res[`${year}-${month}`] || 0) + 1
return res
}, {})
console.log(summary)
Note, above will work if your createdAt strings formatted in any way that may be parsed by new Date() constructor, not only ISO-formatted date.

How do I change date formatting in Javascript to enable sorting?

I am writing my dates of birth in the following manner:
4.02.1976 14:37
1.7.1990 11:35
10.10.1910 18:00
I wanted to sort it using something similar to this code (enabling sorting by birth):
var obj = [{"id":1,"dateOfBirth":"1.7.1990 11:35"},
{"id":4,"dateOfBirth":"4.02.1976 14:37"},{"id":2,"dateOfBirth":"28.10.1950
2:15"},{"id":3,"dateOfBirth":"03.01.1963 23:10"}]
obj.sort(function(a,b) { return new Date(a.dateOfBirth).getTime() - new
Date(b.dateOfBirth).getTime() } );
I am unsure if I need to reformat the dates of birth to achieve this.
Since you just have the year/month/day, it's pretty trivial to split up the dateOfBirth string, convert to a single number, and sort by that number, without any need to mess with Dates:
var obj = [{
"id": 1,
"dateOfBirth": "1.7.1990"
}, {
id: 2,
dateOfBirth: "28.10.1950"
}, {
"id": 4,
"dateOfBirth": "4.02.1976"
}];
function valueFromDOBString(str) {
const values = str.split('.').map(Number);
return values[0] + values[1] * 100 + values[2] * 10000;
}
const sortedObj = obj.sort((a, b) => {
return valueFromDOBString(b.dateOfBirth) - valueFromDOBString(a.dateOfBirth);
});
console.log(sortedObj);
A working version with optional time values.
var obj = [{
"id": 1,
"dateOfBirth": "1.7.1990"
},
{
"id": 4,
"dateOfBirth": "4.02.1976 14:37"
}, {
"id": 2,
"dateOfBirth": "28.10.1950 2:15"
}
];
console.log(
obj.sort(function(a, b) {
return parseDate(a.dateOfBirth) -
parseDate(b.dateOfBirth);
})
);
function parseDate(str) {
var tokens = str.split(/\D/);
while (tokens.length < 5)
tokens.push(0);
return new Date(tokens[2], tokens[1]-1, tokens[0], tokens[3]||0, tokens[4]||0);
}

Filter Array in Array by date between 2 dates

I am trying to filter a data-array of a LineChart by the from-date / to-date input of a user in TypeScript for my Angular App.
The data array has the following structure:
var multi = [
{
"name": "test1",
"series": [
{
"date": new Date("2018-01-01T01:10:00Z"),
"value": 44
},...
]
},
{
"name": "test2",
"series": [
{
"date": new Date("2018-01-01T01:10:00Z"),
"value": 38
},...
]
},
{
"name": "test3",
"series": [
{
"date": new Date("2018-01-01T01:10:00Z"),
"value": 33
},...
]
}
];
I now want to filter the items of the array by the criteria that the date inside is after a 'fromDate' and before a 'toDate'. I tried the following:
obj.forEach(data => {
console.log(data.name);
data.series = data.series.filter((item: any) => {
item.date.getTime() >= fromDate.getTime() &&
item.date.getTime() <= toDate.getTime();
});
});
the obj[] array has an empty obj[i].series array afterwards. Can anybody help me here? The iteration seems to be right since debugging gave me all the dates, also the true/False statements from the date comparing was right as well.
Thanks in advance
You need to return the compairing value, either explicit
data.series = data.series.filter((item: any) => {
return item.date.getTime() >= fromDate.getTime() &&
item.date.getTime() <= toDate.getTime();
});
or without the brackets, implicit.
data.series = data.series.filter((item: any) =>
item.date.getTime() >= fromDate.getTime() && item.date.getTime() <= toDate.getTime()
);
I had an issue with this when the end date was the same as the start date to solve this issue I had to set the time on the end date to 23.59
const start = new Date().getTime()
const end=new Date()
end.setHours(23,59,59,999)
end.getTime()
return items.filter(item => {
let date = new Date(item.created_at).getTime();
return date >= start && date <= end;
}
let start = new Date(this.min);
let end = new Date(this.max);
return items.filter(item => {
let date = new Date(item.created_at);
return date >= start && date <= end;
}

Categories