I have an array of objects. Each object has a date property. I am trying to create a function where I append every item to a new array if the item's date is equal to today's date.
Also, I am not sure if the for loop is the most efficient approach for this, this list will never be more than a few hundred items though.
My function:
todayListItems() {
const todayItems = [];
const todayDate = moment(new Date()).format('dd-mm-YYYY');
for (let i = 0; i < myArray.length; i++) {
const itemDate = moment(myArray[i].date).format('dd-mm-YYYY');
if (itemDate === todayDate) {
todayItems.push(myArray[i]);
}
}
console.log(todayItems);
return todayItems;
}
This function runs but even if there is an item with today's date nothing will be pushed to the array.
You can use Array.filter() and moment#isSame with the second parameter to limit the granularity to a unit other than milliseconds:
function todayListItems(arr) {
return arr.filter(obj => moment().isSame(obj.date, 'day'));
}
todayListItems(myArray);
Demo:
function todayListItems(arr) {
return arr.filter(obj => moment().isSame(obj.date, 'day'));
}
const myArray = [
{ date: '2019-10-14T12:10:00Z'},
{ date: new Date() },
{ date: moment().minutes(120).format('YYYY-MM-DDTHH:mm:ss') },
{ date: new Date('2019-10-23T01:00:00') },
];
console.log(todayListItems(myArray));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
You're formatting wrongly. mm is minutes. The formatting should be DD-MM-YYYY, see https://momentjs.com/docs/#/displaying/format/
Related
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
I have the following array of objects
const monthlyList = [
{
"leave_id":119,
"employee_id":"25528",
"from_date":"2022-03-10",
"to_date":"2022-03-11",
"employee_name":"Name 1"
},
{
"leave_id":120,
"employee_id":"25529",
"from_date":"2022-03-10",
"to_date":"2022-03-13",
"employee_name":"Name 2"
},
{
"leave_id":121,
"employee_id":"25530",
"from_date":"2022-03-15",
"to_date":"2022-03-18",
"employee_name":"Name 3"
},
{
"leave_id":123,
"employee_id":"25530",
"from_date":"2022-03-20",
"to_date":"2022-03-20",
"employee_name":"Name 3"
}
]
I am trying to display the count of leave events for each day in a calendar using FullCalendar. For this, I am trying to get an array in the following format
[
{
"date":"2022-03-10",
"count":2
},
{
"date":"2022-03-11",
"count":2
},
{
"date":"2022-03-12",
"count":1
}
--- etc
]
That is if there are two leaves are there on the same date, the count should be 2. Also, it should calculate the count for all the dates between the from_date and to_date so that I can display the count on the calendar for all the dates that fall between the range.
I use the following code using lodash to group based on from_date and to_date and from there I can create the array above. But not sure how to do it for the days in between
let groupedListFrom = _.groupBy(monthlyList, "from_date");
let groupedListTo = _.groupBy(monthlyList, "to_date");
It will be really helpful if someone can help me here. Thanks
A possible approach using reduce rather than Lodash.
I used https://gist.github.com/miguelmota/7905510 as a helper to get Date objects between two given dates.
const monthlyList = [
{
"leave_id":119,
"employee_id":"25528",
"from_date":"2022-03-10",
"to_date":"2022-03-11",
"employee_name":"Name 1"
},
{
"leave_id":120,
"leave_id":"25529",
"from_date":"2022-03-10",
"to_date":"2022-03-13",
"employee_name":"Name 2"
},
{
"leave_id":121,
"employee_id":"25530",
"from_date":"2022-03-15",
"to_date":"2022-03-18",
"employee_name":"Name 3"
},
{
"leave_id":123,
"employee_id":"25530",
"from_date":"2022-03-20",
"to_date":"2022-03-20",
"employee_name":"Name 3"
}
]
//a function to get Date objects between two given dates (inclusive)
//https://gist.github.com/miguelmota/7905510
const getDates = (startDate, endDate) => {
const dates = []
let currentDate = startDate
const addDays = function (days) {
const date = new Date(this.valueOf())
date.setDate(date.getDate() + days)
return date
}
while (currentDate <= endDate) {
dates.push(currentDate)
currentDate = addDays.call(currentDate, 1)
}
return dates
}
let x = Object.values(monthlyList.reduce((acc,{leave_id,employee_id,from_date,to_date,employee_name})=>{
const dates = getDates(new Date(from_date), new Date(to_date));
dates.forEach((date) => {
let strippedDate = date.toISOString().substring(0,10);
if(!acc[strippedDate])acc[strippedDate]={date:strippedDate,count:0};
acc[strippedDate].count+=1
})
return acc;
},{}))
console.log(x)
var DateTime = require('luxon').DateTime;
let leavesArray = {};
monthlyList.forEach(x => {
let a = DateTime.fromFormat(x.from_date,"yyyy-MM-dd")
let b = DateTime.fromFormat(x.to_date,"yyyy-MM-dd")
while (a <= b) {
let date = a.toFormat("yyyy-MM-dd");
if (leavesArray[date]) {
leavesArray[date]["count"]++;
} else {
leavesArray[date] = {}
leavesArray[date]["count"] = 1;
} a = a.plus({days: 1})
}
})
Node Js Working solution
I am working on something with React Native Calendar. I need to get all the dates between two dates and marked these in React Native Calendar.
I have the start and the end date that are now in an array, I also can have the date between these but only if I specify with values I want from my array. The idea's that I want the function to get all the first/second / third and so on values and automatically calculate the date between these and finally marked these in my calendar. I can't have my all dates on this calendar actually.
How can I do that ? Thank you in advance here is my code :
try {
let res = await axios.get(`https://myseenapp.herokuapp.com/constructionSite/${_id}`);
let data = res.data;
setConstruction(data);
setStartDate(
data
.map(e => e.startDate)
.forEach((day) => {
let convert = day.split('-').reverse().join('-')
if (arrayStart.includes(convert) === false) {
arrayStart.push(convert)
}
}));
setEndDate(
data
.map(e => e.endDate)
.forEach((day) => {
let convert = day.split('-').reverse().join('-')
if (arrayEnd.includes(convert) === false) {
arrayEnd.push(convert)
}
}));
}
catch (err) {
console.log(err)
}
};
let end = moment(arrayEnd[0]);
let start = moment(arrayStart[0]);
const getDaysBetweenDates = (start, end) => {
let now = start;
let dates = [];
while (now <= end){
dates.push(now.format("YYYY-MM-DD"));
now.add(1, 'days');
dates.forEach((day) => {
newDaysObject[day] = {
textColor: "white",
color: 'gold',
selected: true,
}
})
}
return dates;
}
let dateList = getDaysBetweenDates(start, end);
console.log(dateList)
const getDaysBetweenDates = (start, end) => {
let now = start;
let dates = [];
while (now <= end){
dates.push(now.format("YYYY-MM-DD"));
now = momet(now).add(1, 'days'); // you are updating the same object again and again, so here I am creating new object
}
// moving this out so it runs only when all the dates are filled in array
// this should have been done outside this method for cleaner code
dates.forEach((day) => {
// not sure where this object came from.
newDaysObject[day] = {
textColor: "white",
color: 'gold',
selected: true,
}
});
return dates;
}
There is an object array like this:
[
{
timestamp: 1318781876
any: 'other fields'
}
]
Of course there are multiple objects in that array. I am using momentJS - if it matters here...
Now I need to split that array into months. That means I need to get all objects for 'july' to display them in a table.
Is this possible at all or should I change the datastructure? I thought using timestamp is the best option, as I could calculate everything from this.
But now I'm thinking if I have to add month and year field to the object...
You could iterate the array and build up a tree, may also write year and month to the objects:
var map={};
array.forEach(function(obj){
var d = new Date(obj.timestamp*1000);
var m = obj.month = d.getMonth() +1;
var y = obj.year = d.getFullYear();
if(!map[y]) map[y]={};
if(!map[y][m]) map[y][m]=[];
map[y][m].push(obj);
});
So now weve got a map like this:
map: {
2017 : {
8 : [
{
timestamp:123456,
month:8,
year:2017,
any:"other value"
}
]
}
}
So you can now get all julys by:
map[2017][7]
It depends if you just do this once, then other answers will be easier, but if you need different timeranges the upper code just needs to iterate once, and you can get the filtered results easily. To get sorted results:
var sorted=Object.keys(map)/*the years*/ .sort().map(function(year){
return { year, months: Object.keys(map[year]).sort().map(function(month){
return {month,results:map[year][month]};
})
};
});
These arrays may already be built up while building the hash table, see ninas way of doing this
This can be done using array.filter
myArr = [
{
timestamp: 1318781876
any: 'other fields'
}
...
];
var filteredArray = myArr.filter(function(item) {
return (item.timestamp > minOfDateRange && item.timestamp < maxOfDateRange);
});
Your structure is quite useful. You can use Array.filter:
const startDate = new Date(2017, 6, 1); // 6 for July
const endDate = new Date(2017, 7, 1);
const selectedData = data.filter(entry => startDate <= entry.timestamp * 1000 && entry.timestamp * 1000 < endDate)
Convert the milisecond to a date using following code and get the month afterward
var date = new Date(milliseconds);
var month = date.getMonth();
then put the july object to another array and display them as you wish
You can use a hashmap approach.
var arr = [
...
{
timestamp: 1318781876
any: 'other fields'
}
...
];
var grouped = {};
var months = ['Jan', 'Feb' ...];
arr.forEach( function(item){
var dateObj = moment.unix(item.timestamp);
var month = months[dateObj.month()];
if(!grouped[month]){
grouped[month] = [];
}
grouped[month].push(item);
});
console.log(grouped);
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,}
}
`