Javascript functional programming and dynamic values in an Array - javascript

I am trying to write a function that grabs the first 14 days (starting today) with momentJS. My function currently looks like
let dateArr = Array(14).fill(moment())
.map((date) => {
return date.add(1, 'days')
});
I understand that fill is for static values and not dynamic ones, so how would I go about fixing this up so that I have an array that has, ['11/12', '11/13', '11/14', etc...]
I think i need some sort of recursion so that it adds 1 day from the last iteratee, or else i think it'll just keep adding 1 day from today for each iteration

Array(14).fill(moment())
.map((date, i) => date.add(1, 'days').format('MM/DD'));
OUTPUT:
(14) ["01/13", "01/14", "01/15", "01/16", "01/17", "01/18", "01/19", "01/20", "01/21", "01/22", "01/23", "01/24", "01/25", "01/26"]
UPDATE:
Start from today^
Array(14).fill(moment())
.map((date, i) => {
if(i === 0) {
return date.format('MM/DD')
}
return date.add(1, 'days').format('MM/DD')
});
(14) ["01/12", "01/13", "01/14", "01/15", "01/16", "01/17", "01/18", "01/19", "01/20", "01/21", "01/22", "01/23", "01/24", "01/25"]

What you are doing is filling an array with a SINGLE date object, like doing this:
let date = moment();
let dateArr = Array(14).fill(date)
.map((date, index) => {
return date.add(index, 'days')
});
moment.add() will not return a new date object, but modify the current date object. What you need is to retrieve a new date object on each map (instead of returning the same date object):
let dateArr = Array(14).fill(moment())
.map((date, index) => {
return date.clone().add(index, 'days'); // Note the `clone()` so a new object is created.
});
And if you want to just retrieve a string, just add a format:
let dateArr = Array(14).fill(moment())
.map((date, index) => {
return date.clone().add(index, 'days'.format('MM/DD'); // Note the `clone()` so a new object is created.
});
Also note how a index is used to add days dinamically depending on the array position, hence first position will be today (adding 0 days).

I hope I understand you right. You will get all days from maybe today +14 days in the future. But I dont understand why you will use fill() methode?
Then that will work for you:
var getDaysArray = function(year, month, day) {
var date = new Date(year, month, day);
var result = [];
var i;
for (i=0;i<14;i++) {
result.push(date.getMonth() + '/' + date.getDate());
date.setDate(date.getDate() + 1);
}
return result;
}
console.log(getDaysArray(2021,1,12) )

Related

Get Previous and Next Days

I am pulling varchar dates from a db table, and trying use them to get the date of both the previous day and next day. In the example below, I would have grabbed 2020-03-26 from my table. I am trying to figure out how to get both 2020-03-25 and 2020-03-27 saved as variables that I can then use. I have figured out that in order to get the date the exact format that I want I have to use the toISOString and slice off the first 10 characters, but I am unsure how to get the previous and next days, especially if a month crossover had occurred.
var tableDate = new Date('2020-03-26')
tableDate = tableDate.toISOString().slice(0,10)
Try this one:
let tableDate = new Date('2020-03-26');
// function to increment
function incrementDate(date, days) {
let result = new Date(date);
result.setDate(result.getDate() + days);
return result;
}
// funtion to decrement
function decrementDate(date, days) {
let result = new Date(date);
result.setDate(result.getDate() - days);
return result;
}
console.log(incrementDate(tableDate, 1).toISOString().split('T')[0]);
console.log(decrementDate(tableDate, 1).toISOString().split('T')[0]);
The decidedly easiest way is using dayjs.
With it set up you'd use it something like,
const tableDate = new Date('2020-03-26')
const dayBefore = dayjs(tableDate).subtract(1, 'day')
const dayAfter = dayjs(tableDate).add(1, 'day')
You can then apply .toISOString(), or you can simply use .format() to get the exact output you'd prefer from the outset.

How can i get the first nearest date in the past?

I have this arrays
const datesToBeChecked = ['2020-07-03','2020-07-06', '2020-07-13', '2020-07-20']
const dateToCheckFor = '2020-07-12';
I need to get the first nearest date in the past - so when the date is 2020-07-12 i need to get
2020-07-06 from datesToBeChecked.
WHAT I TRIED
I tried this code
datesToBeChecked.forEach(date => {
let diff = moment(dateToCheckFor).diff(moment(date), 'days');
console.log(diff);
if (diff > 0) {
if (nearestDate) {
if (moment(date).diff(moment(nearestDate), 'days') < 0) {
nearestDate = date;
}
} else {
nearestDate = date;
}
}
});
but that gives me the earliest date in the array - 2020-07-03. But i need the first BEFORE THE DATE I CHECK FOR
Actually your logic is almost there. You don't need the nested if conditional. In essense, what you want is to cache the difference, and compare the current difference with the cached difference. If the cached difference is smaller, then we know the current date is the nearest one. Otherwise, we continue for the search.
This solution will work even if the dates are not sorted in chronological order (oldest to newest):
const datesToBeChecked = ['2020-07-03', '2020-07-06', '2020-07-13', '2020-07-20']
const dateToCheckFor = '2020-07-12';
let nearestDate;
let cachedDiff = Infinity;
datesToBeChecked.forEach(date => {
let diff = moment(dateToCheckFor).diff(moment(date), 'days');
if (diff > 0 && diff < cachedDiff) {
cachedDiff = diff;
nearestDate = date;
}
});
console.log(nearestDate);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
The first element is the closest date in the past (at least yesterday, today results won't show up).
If empty then dateToCheckFor elements does not contain any date in past.
const mappedDates = dateToCheckFor
.map(d => moment(dateToCheckFor).diff(moment(d), 'days'))
.filter(diff => diff <= -1)
.sort()
.reverse();
You could try sorting all of the dates in a hash table first. So you would have a hash table:
{
date1: difference,
date2: difference,
...
}
then you would sort the objects values, such as here: Sorting object property by values
then take the first date from that, which is before the dateToCheckFor
I hope this is not too inefficient for you.
Here's one way with good ole vanilla js. Moment.js weighs 230+kb
const datesToBeChecked = ['2020-07-03', '2020-07-06', '2020-07-13', '2020-07-20']
const dateToCheckFor = '2020-07-12';
dateToCheckFor_d = new Date(dateToCheckFor).getTime();
let possibilities = datesToBeChecked.filter(dt => {
return (new Date(dt).getTime() < dateToCheckFor_d)
})
possibilities.sort().reverse()
console.log(possibilities[0])
In your code just update the below line
if (moment(date).diff(moment(nearestDate), 'days') < 0
to
if (moment(date).diff(moment(nearestDate), 'days') > 0

exact string match is not returning true in JavaScript filter helper

I'm using a filter helper to create a new array of items that match today's date. I've confirmed that the two comparisons are both a string with a length of 10, yet they're not being recognized as a match when compared in a filter.
I know it has to do with the new Date() method because the first comparison works when I test it against a string of the date while the new Date method does not.
if(chosenDate === 'today') {
// this does not work even though both values are equal
const scheduled = this.props.scheduled.filter(event => event.scheduled_at.substring(0, 10) === new Date(), 'yyyy-MM-dd');
// this works
const scheduled = this.props.scheduled.filter(event => event.scheduled_at.substring(0, 10) === '2019-11-14');
// this does not work
const scheduled = this.props.scheduled.filter(event => '2019-11-14' === new Date(), 'yyyy-MM-dd');
console.log(scheduled)
}
console.log(this.props.scheduled[0].scheduled_at.substring(0, 10));
console.log(dateFnsFormat(new Date(), 'yyyy-MM-dd'));
Why is new dates string not comparing equally?
It seems like you meant
const scheduled = this.props.scheduled.filter(event =>
event.scheduled_at.substring(0, 10) === dateFnsFormat(new Date(), 'yyyy-MM-dd')
);
but wrote
const scheduled = this.props.scheduled.filter(event =>
event.scheduled_at.substring(0, 10) === new Date()
, 'yyyy-MM-dd'
);

How can I get actual date in this format?

I want to compare the actual date to a format like this that I'm receiving from a server:
item.expires_date.slice
"2016-11-28 22:10:57 Etc/GMT"
In javascript how could this be possible? specially for the part Etc/GMT
In the case I just wanted to compare 2016-11-28
how can I achieve this:
var today = new Date().toISOString().slice(0, 10);
if(item.expires_date.slice(0, 10) > today) {
console.log("This item have expired");
} else {
console.log("this item has not expired" );
}
}
it does not work because it brings to item has not expired comparing dates:
2016-11-28 - 2016-12-28
Thanks!
Since "Etc/GMT" is the same as "GMT+00:00", you can remove it and create a Date object from the string:
var s = "2016-11-28 22:10:57 Etc/GMT";
var d = new Date(Date.parse(s.replace("Etc/", "")));
console.log(d.toString());
Then you can compare d to the current date.

Trying to remove all the passed dates

I have an array with many dates, they are not in the date type but string like: "2016-08-12" for example. Then what I would like to do is to remove all dates that we already have passed. So therefor im trying to compare them to todays date and then remove it if its passed. Using typescript by the way.
my array, named datoArray, looks like this:
["2016-08-02", "2016-08-11", "2016-08-22", "2016-09-10"]
just with a lot more of the same...
then here's what I try to do:
for(var i = 0; i < this.datoArray.length; i++){
this.skoleAar = parseInt(this.datoArray[i].slice(0,4))
this.skoleMaaned = parseInt(this.datoArray[i].slice(5,8))
this.skoleDag = parseInt(this.datoArray[i].slice(8,10))
if(this.skoleAar < dagensAar){
this.datoArray.splice(i, 1);
}
if(this.skoleAar == dagensAar && this.skoleMaaned < dagensMaaned){
this.datoArray.splice(i, 1);
}
if(this.skoleAar == dagensAar && this.skoleMaaned == dagensMaaned && this.skoleDag < dagensDag){
this.datoArray.splice(i, 1);
}
}
the "dagensAar", "dagensMaaned" and "dagensDag" variables im getting from another function that works. If i "console.log" the variables it prints out int values like 2016 for the year and 8 for the month if i take from the start of the array, and for the "dagensAar", "dagensMaaned" and "dagensDag" it prints 2016 11 20, which is todays year, month and day. all is in Int type, so what im not getting here is why my "if" doesnt work? It seems like there is something wrong with the way i compare the, but i thought this was the way to compare int values?
If the dates are in ISO-8601 format then you can simply filter using Date.parse().
var dates = ["2016-08-02", "2016-08-11", "2016-08-22", "2016-09-10", "2016-12-15"];
function removePastDates(data) {
var today = new Date();
console.log('Initial state: ' + data);
var modified = dates.filter(function(dateString) {
return Date.parse(dateString) >= today;
});
console.log('Final state: ' + modified);
return modified;
}
var newDates = removePastDates(dates);
Your dates seem to be RFC compliant, meaning they can be directly fed into a new Date object. Simply compare to today and filter by that:
var today = new Date()
var futureDates = this.datoArray.filter(d => new Date(d) >= today)
(pre-ECMA6:)
var today = new Date()
var futureDates = this.datoArray.filter(function (d) {
return new Date(d) >= today;
})
I think the problem is not related to the dates.
I think the problem is that you are removing items from the array while looping the same exact array.
You should maybe try looping from the end of the array to the beginning or just save the indexes that you need to remove and later do the actual removing.
Keep in mind that when you remove an item you change the index of every item in the remaining of the array - maybe you should start removing from the greatest index so it will not confuse you.

Categories

Resources