Find if date is the next valid date from today Momentjs - javascript

This is a straight question but I don't find any suitable solution. Given an array of dates, ie
['2015-01-01', '2015-04-20', ...]
Is there any way to check if a item of the array is the next valid date after today?
I am using moment.js.

[…] Is there any way to check if a item of the array is the next valid date after today?
Your description is not really clear to me, but it sounds like you’re trying to programmatically determine if an array of dates contains tomorrow’s date (i.e. “the next valid date after today”). In that case, read on:
First, get tomorrow’s date in the same format as the strings in your array using moment.js:
var tomorrow = moment().add(1, 'days').format('YYYY-MM-DD');
Now you can just loop over the array and compare each value to tomorrow using == or === (doesn’t matter in this case):
dates.forEach(function(date) {
if (date == tomorrow) {
// Bingo!
}
});
If you just want to check if any of the dates in the array are tomorrow’s date, use Array#some:
var containsTomorrow = dates.some(function(date) {
return date == tomorrow;
});

This can actually be solved without using momentjs
var todaysDate = new Date();
var min;
var index;
var array = ['2015-01-01', '2015-04-20', ...];
for (var i = 0; i < array.length; i++) {
var inputDate = new Date(array[i]);
var ts = inputDate - todaysDate;
if (!min || (ts < min && ts > 0) ) {
min = ts;
index = i;
}
}
// index will contain the index of the nearest next date

Related

Date validation and relative delta between two dates in javascript

I have an interface where I receive a date in this format: Month/Year, ex: 11/2022.
I would like to verify that this is a valid date.
I use the datatables editor. The configuration (see below) of the field works well, but since the user can enter the date himself without going through the calendar, there is a risk that the date entered is incorrect. It doesn't work like an input mask. So i need to validate the date in the code.
{
type: "datetime",
label: "Date:",
name: "Date",
def: function () { return new Date(); },
format: 'MM/YYYY',
fieldInfo: 'Format: Month/Year (ex: 12/2022)',
keyInput: true
}
The date should not be accepted if the difference between this date and today's date is less than 3 months.
It means that, compared to today, all dates before July will have to be rejected.
Currently I can do this with the relativedelta method of the python dateutil module. But as the validation must be done on the client side, I would like to do this in javascript (which I know very little).
The example below shows how to do this. You should take advantage of the HTML 5 input types to validate your dates. You also need to calculate 3 months from now in myEpoch and then compare it to the date/time given
HTML:
<p>
Date & Time: <input id="foo" type="datetime-local" />
</p>
JavaScript:
var myEpoch = new Date();
myEpoch.setMonth(myEpoch.getMonth() + 3);
myEpoch = myEpoch.getTime();
var foo = document.getElementById("foo");
if (foo.value < myEpoch) {
//show a message saying this date is invalid
}
Since user is entering date in MM/yyyy format, so i'm assuming that you take 1 as a date into account, i.e., if input is 03/2020, you would consider it as: 01/03/2020. Right? If
so, then you can do the following to validate this date:-
function isValidDate(inputDate) {
// Unfortunately JS doesn't have any in-built function to validate date in MM/yyyy format. Hence regex comes to the rescue
var regex = /^([0-9]{1,2})\/([0-9]{4,4})$/;
var matches = regex.exec(inputDate);
if (!matches || matches.length != 3) {
throw new Error('Please provide date in MM/yyyy format');
}
var inputMonth = matches[1]; // Return month from input date
var inputYear = matches[2]; // Return year from input date
var finalDate = inputMonth+ '/01/' + inputYear;
// Check if entered date is valid or not
var parsedDate = Date.parse(finalDate);
if (isNaN(parsedDate)) {
throw new Error('Unable to parse date.');
}
// Check if it is less than 3 months or not.
var isValid = !isLessThan3Months(new Date(finalDate), new Date());
return isValid;
}
function isLessThan3Months(dateToCompare, currentDate) {
var diffYears = currentDate.getFullYear() - dateToCompare.getFullYear();
var diffMonths = currentDate.getMonth() - dateToCompare.getMonth();
var diffDays = currentDate.getDate() - dateToCompare.getDate();
var months = diffYears * 12 + diffMonths;
if (diffDays > 0) {
months += '.' + diffDays;
} else if (diffDays < 0) {
months--;
months +=
'.' +
(new Date(currentDate.getFullYear(), currentDate.getMonth(), 0).getDate() + diffDays);
}
return months < 3;
}
isValidDate('03/2020');
So now, by calling isValidDate with user's input date in MM/yyyy format, you should be able to check if it is valid or not.
For this, you won't need to use any third party javascript library. Just plain javascript is enough.
You should probably use Moment.js, because working with the raw Date object is fiddly.
If you would rather use plain JavaScript, then the following might be of use:
const moreThan3MonthsHence = ({ utcYear, utcMonth },
now = new Date,
target = new Date(Date.UTC(utcYear, utcMonth)),
threeMonthsHence = addMonths(new Date(now.valueOf()), 3)) =>
(target > threeMonthsHence)
const validate = (str,
[utcMonth, utcYear] = str.split('/'),
date = new Date(Date.UTC(+utcYear, (+utcMonth)-1))) =>
moreThan3MonthsHence({ utcYear: date.getUTCFullYear(), utcMonth: date.getUTCMonth() })
const addMonths = (date, months, d = date.getDate()) => {
date.setMonth(date.getMonth() + +months);
// If rolled over to next month, set to last day of previous month
if (date.getDate() != d) {
date.setDate(0);
}
return date;
}
// Note: input is one-based months
console.log(validate('07/2020')) // true
console.log(validate('06/2020')) // false
console.log(validate('12/2019')) // false
Notes
now is internally represented as the milliseconds since the Unix epoch. Note this includes the current time of day.
target is the milliseconds since the Unix epoch of midnight on the supplied UTC date.
threeMonthsHence is the milliseconds since the Unix epoch of now (including time of day), plus three months.
validate parses the input string.
addMonths is necessary because the built-in function can roll-over into a new month with unexpected behavior.
Finally to solve my problem I mixed the solutions proposed by #Sumit Parakh and #ControlAltDel.
function isValidDate(inputDate) {
var regex = /^([0-9]{1,2})\/([0-9]{4,4})$/;
var matches = regex.exec(inputDate);
var parsedDate = 0;
if (!matches || matches.length != 3) {
throw new Error('Please provide date in MM/yyyy format');
}
else {
var inputMonth = matches[1]; // Return month from input date
var inputYear = matches[2]; // Return year from input date
var finalDate = inputMonth+ '/01/' + inputYear;
// Check if entered date is valid or not
var parsedDate = Date.parse(finalDate);
if (isNaN(parsedDate)) {
parsedDate = 0;
//throw new Error('Unable to parse date.');
}
return parsedDate;
}
var myEpoch = new Date();
myEpoch.setMonth(myEpoch.getMonth() + 3);
myEpoch = myEpoch.getTime();
finalDate = isValidDate(date_peremption.val());
if (finalDate == 0){
date_received.error("This date is invalid");
}
else if(finalDate < myEpoch) {
date_received.error("The date must be more than three months last");
}
It's not very elegant, but it works. Thanks everyone

get todays date in javascript in format yyyy-mm-ddT00:00:00

Hello i am new to javascript , i tried a lot i cant get this format
yyyy-mm-ddT00:00:00, i want to get this format in java script to compare it with other dates in an array and then get the next valid date that will come .
also if some one can show me a function on how to compare and get the closest greater date than today .
datesarray = ['2017-12-09T00:00:00' ,'2017-12-13T00:00:00' ,'2017-12-02T00:00:00' ,'2017-12-16T00:00:00']
let diffDate = Infinity;
let now = Date.now;
for (let i = 0; i < datesarray.length; i++) {
let closest = datesarray[0];
if (closest > now && closest < diffDate)
{
diffDate = closest;
}
}
this is what i tried but its never getting into the if statement .
PS : i have other dates in an array but i did not show them here .
I think you have two separate questions here, to get an iso formatted date string you would use Date.prototype.toISOString(), but to compare dates and find the closest you would need to turn those strings into date objects and compare
let datesArray = ['2017-12-09T00:00:00' ,'2017-12-13T00:00:00' ,'2017-12-02T00:00:00' ,'2017-12-16T00:00:00'];
let diffDate = Infinity;
let now = Date.now();
for (let i = 0, len = datesArray.length; i < len; i++) {
let closest = new Date(datesArray[i]);
if (closest > now && closest < diffDate) {
diffDate = closest;
}
}
console.log(diffDate.toISOString());
Edit 1
In answer to your question, I can't duplicate your undefined problem using the code above, and to illustrate that diffDate is set correctly I moved it outside of the loop, if you run the snippet you should see the closest date print.
That being said, this might be a more concise way to handle your problem as long as modern JS syntax is workable for your issue.
const datesArray = ['2017-12-09T00:00:00' ,'2017-12-13T00:00:00' ,'2017-12-02T00:00:00' ,'2017-12-16T00:00:00'];
const dateCompare = (closest, current) => {
const t = new Date(current);
return (t > Date.now() && t < closest) ? t : closest;
}
let closest = datesArray.reduce(dateCompare, Infinity)
console.log(closest.toISOString());
Edit 2
To handle timezone precision problems if possible you want your date array to have dates in iso format 'yyyy-mm-ddThh:mm:ssZ' | '2017-12-02T00:00:00Z' if you can't edit your date array format you should make sure to append that 'Z' before creating your date: new Date(current + 'Z');
For your first question, use the ISOString() function of the Date object.
https://www.w3schools.com/jsref/jsref_toisostring.asp
For the next one, either create date object of each time, and then compare, or if you need to support equality check, convert all to milliseconds from the date object.
Use the Date() object. There are many different ways to enter the date. One is what you are using.
var dateArray = [new Date('2017-12-09T00:00:00'), new Date(2017, 11, 13), new Date(2017, 11, 2), new Date(2017, 11, 16)];
var today = new Date();
var closestDate = new Date(5000, 0, 0);
for (var i = 0; i < dateArray.length; i++) {
var curr = dateArray[i];
if(curr > today && curr < closestDate) {
closestDate = new Date(curr);
}
}
console.log(closestDate); // Prints Sat Dec 02 2017 00:00:00 GMT-0500 as of 10/19/2017

Check if a date is between two dates

I have an array with different dates with the format of year-month-day.
something like this:
var dates = ["2016-08-01", "2016-08-09", "2016-08-10", ....];
I also have a function that formats todays date in the same format as above. And is stored in a variable:
var currentDate; //Contains current date in the format of year-month-day
What i need to do is to check if any of the dates in the array, either:
Match with today's date.- e.g. Today would be 2016-08-13
Match with 14 days back from today's date. - e.g. 14 days back from today (2016-08-13) would be 2016-07-30
Or match with any dates between the current and 14 days back.
I'm trying to do this by looping through the array, checking each value. But im unsure about the if condition/conditions
for(var i = 0; i < dates.length; i++) {
if(currentDate === *condition*) {
sendDate(dates[i]);
}
}
Anyone have a good solution for this? Thanks in advance!
Firstly, create a new Date() from your currentDate ( currentDate is string format Y-d-m with hour and minutes is 00:00)
var current = new Date(currentDate);
var matchWithCurrent = [];
var matchWithDayBack = [];
var between = [];
just loop through your date array
for (var i=0; i<dates.length; i++) {
var tmpDate = new Date(dates[i]); //Convert string to date
var diff = Math.ceil((current - tmpDate) / (1000 * 3600 * 24)); //get time difference (current - tmpDate is milisecond, we need convert it to day)
// Check condition and push it on array correct
if (diff == 0) {
matchWithCurrent.push(dates[i]);
}
if (diff == 14) {
matchWithDayBack.push(dates[i]);
}
if ((diff > 0) && (diff <14)) {
between.push(dates[i]);
}
}
console.log(matchWithCurrent);
console.log(matchWithDayBack);
console.log(between);
If you want only one array match with 3 condition just check 3 condition in only one if and push it into your result array
One way would be to parse the dates to millisecond values and compare them.
var todayParts = currentDate.split('-');
var today = new Date(todayParts[0], todayParts[1], todayParts[2]).getTime();
var otherParts = dates[i].split('-');
var other = new Date(otherParts[0], otherParts[1], otherParts[2]).getTime();
if (today < other + 1209600000 /* 2 weeks in milliseconds */) {
// The other date is less than 2 weeks before today
}
You can read here why I parsed it manually instead of using Date.parse().
You can compare two dates something like that:
var currentDate = new Date();
for(var i = 0; i < dates.length; i++) {<br>
var arrDate = new Date(dates[i]);
if(currentDate == arrDate)
{//compare array dates with current date
//your code here
}
var beforeDate = (currentDate.getDate() - 14); //14 days before
if(arrDate >= beforeDate && arrDate <= currentDate){
//compare dates between current date and 14 days before date
}
}

If date between date range

I'm working with two dates, e.g. 29/03/2014 and 04/04/2014, and I have an array of dates e.g. 01/04/2014 and 02/04/2014, I need to find out how many (if any) dates in that array are between the date range.
What's the best way to do this?
EDIT: Final code, tweaked a little from ponciste's answer
//date1 and date2 are the start/end dates
bhDays = new Array();
$.each(DataBridge.bankHolidays, function(i, v) {
var americanDate = v.split('-');
americanDate = americanDate[1] + '/' + americanDate[0] + '/' + americanDate[2];
date = new Date(americanDate);
if (date1 <= date && date2 >= date) {
bhDays.push(date);
}
});
it's better to deal with Date object in this case
so your code should be something like this:
var strDateFrom = "29/03/2014";
var strDateTo = "04/04/2014";
var dateFrom = strDateFrom.split("/");
var dateTo = strDateTo.split("/");
var dates = ["01/04/2014", "02/04/2014"];
var from = new Date(dateFrom[2], dateFrom[1]-1, dateFrom[0]);
var to = new Date(dateTo[2], dateTo[1]-1, dateTo[0]);
dates.forEach(function(date) {
var dateToCheck = new Date(date[2], date[1]-1, date[0]);
if(dateToCheck > from && dateToCheck < to)
});
The Date object will do what you want - construct one for each date, then just compare them using the usual operators.
Construct your date objects and compare using < || > operators.
I strongly reccoment to use moment.js library for that (and all other operations with date/time) and use difference function.

Interpret user entered dates in JavaScript

I was looking for a convenient method to take a date entered by a user and do the following:
1) Determine if the Date entered is valid, and if it is valid, return an object with:
2) A JavaScript Date object
3) The date formatted in mySQL format (YYYY-MM-DD)
4) The date formatted in typical format (MM-DD-YYYY)
In the end I wrote my own function that uses Regex and can handle an input of YYYY-MM-DD, YYYY/MM/DD, MM-DD-YY, MM/DD/YY, MM-DD-YYYY or MM/DD/YYYY.
The reason that the function returns mySQL format and regular format in the object is simply for convenience. My web app needs the typical format to display in the field and the mysQL format to send to the server when saving data.
The code is shown below in my answer. I'm sure there are ways to optimize the code, but I wrote it in parts for the ease of reading. And even if it was set to run every time a user entered data in a date field, it wouldn't bog anything down. Hopefully this helps someone!
UPDATE: momentjs is much better.
The code and an example can be seen here on this jsfiddle.
function interpretDate(stringDate){
var mysqlF = "(\\d{4})[-/](\\d{1,2})[-/](\\d{1,2})";
var dispF = "(\\d{1,2})[-/](\\d{1,2})[-/]((?:\\d{4})|(?:\\d{2}))";
var dispNoYearF = "(\\d{1,2})[-/](\\d{1,2})";
var dateFormats = "(^"+mysqlF+"$)|(^"+dispF+"$)|(^"+dispNoYearF+"$)";
//Let's try to extract the data
data = stringDate.match(dateFormats);
var month = -1;
var day = -1;
var year = -1;
//Check to see if the verification failed
if (data == undefined){
//Invalid date
return {valid: false, date: null, mysqlDate:null, displayDate: ""};
}
//Extract the data based on the entry type
if (data[1] != undefined){//YYYY-MM-DD
month = parseInt(data[3]);
day = parseInt(data[4]);
year = parseInt(data[2]);
}else if (data[5] != undefined){//MM-DD-YYYY or MM-DD-YY
month = parseInt(data[6]);
day = parseInt(data[7]);
year = parseInt(data[8]);
if (year < 100){
var yearString = new String(new Date().getFullYear());
year = parseInt(yearString.substr(0,2) + year);
}
}else if (data[9] != undefined){//MM-DD
month = parseInt(data[10]);
day = parseInt(data[11]);
year = parseInt(new Date().getFullYear());
}
//If we are here, we have three numbers, let's see if they make a real date
var extractedDate = new Date(year, month-1, day);
if (extractedDate.getFullYear() != year || extractedDate.getDate() != day || extractedDate.getMonth() != (month-1)){
return {valid: false, date: null, mysqlDate:null, displayDate: ""};
}
//We have a valid date, let's add front zeros
var monthFixed = month;
if (monthFixed < 10) monthFixed = "0"+monthFixed;
var dayFixed = day;
if (dayFixed < 10) dayFixed = "0"+dayFixed;
//We are done
return {valid: true, date: extractedDate, mysqlDate:year+"-"+monthFixed+"-"+dayFixed, displayDate: month+"/"+day+"/"+year};
}

Categories

Resources