Checking if a string matches dates? - javascript

If we have a text search field that the user types 11/25/2014 and we have an array of dates:
var dates = [ new Date(2014, 11, 25), new Date(2014, 11, 24) ];
How should we go about checking whether the string entered matches any of the dates?
I assume would first see whether it's actually a valid Date, as the user could have entered foo and new Date('foo') is an invalid date.
After that is the some of of includes like we do with strings for the Javascript Date API?

You can format the dates using date functions and construct the desired format and compare it with the input date, look for the index of the formatted date inside the array using findIndex :
const input = "11/25/2014";
var dates = [new Date(2014, 11, 25), new Date(2014, 11, 24)];
const exists = str => dates.findIndex(date => {
const day = date.getDate();
const monthIndex = date.getMonth();
const year = date.getFullYear();
return `${monthIndex}/${day}/${year}` === str;
}) > -1 ? true : false;
console.log( exists(input) )

Yeah you need to validate that the input date is actually a valid date, after that you could check if timestamp for input date matches with some of the dates into array, this could could help you
const isValidDate = (inputDate, dates) => {
const now = new Date(inputDate);
if (isNaN(now)) {
throw new Error(`${inputDate} is not a valid date`);
// or return false instead
}
// this will return the first date that matches with the input date
return dates.some(d => d.getTime() === now.getTime());
}
Please remember that you actually need to validate the format for the input date, so if the date must keep dd/mm/YYYY you must to validate that the input date keeps that format.

It really depends on exactly how consistent you expect their input to be. If you're always going to be getting a date that looks like 'DD/MM/YYYY' with no variation, then you're in a good place and can do something quite easy.
const userDate = new Date(inputText);
const dates = [ new Date(2014, 11, 25), new Date(2014, 11, 24) ];
const hasMatch = dates.some(d => d.getTime() === userDate.getTime());

You need to compare the milliseconds of dates to compare. Also remember that the month is 0-based so your list is actually December.
const input = '12/25/2014';
const test = new Date(input).getTime();
return !isNaN(test) && [new Date(2014, 11, 25), new Date(2014, 11, 26)]
.map(d => d.getTime())
.includes(test)
One thing to note is depending on the input, browsers are very inconsistent in what formats parse when using new Date(str), so if you want to cover more input formats use something like momentjs

Stackblitz
const input = "11/25/2014";
let result = [];
if (!isNaN(new Date(input).getTime())) {
result = dates.filter(date=> {
const day = date.getDate();
const monthIndex = date.getMonth();
const year = date.getFullYear();
const dateString = `${monthIndex}/${day}/${year}`;
return dateString.includes(input);
});
}
console.log("The dates that match are: ", result);
console.log("Two dates match: ", result.length == 2);

Related

Trying to check if the 2 dates are in the same week

I am using date-fns to check if the 2 dates are on the same week or not.
following the documentation If I do :
const isSameWk = isSameWeek(
new Date("2023-02-05"),
new Date("2023-02-06"),
{ weekStartsOn: 0, locale: "en-GB" }
);
If I do the above snippet it will say true which is correct but it throws the error that I need to use parseISO since the new beta v2
so using parseISO
this way
const isSameWk = isSameWeek(
parseISO(new Date("2023-02-05")),
parseISO(new Date("2016-02-06")),
{ weekStartsOn: 0, locale: "en-GB" }
);
or
const isSameWk = isSameWeek(
parseISO("2023-02-05"),
parseISO(("2016-02-06")),
{ weekStartsOn: 0, locale: "en-GB" }
);
would not throw the error but console logging just this parseISO("2023-02-05") gives me the correct but not in my locale and logging parseISO(new Date("2023-02-05")) would give invalid date
Stuck on this for a long time can't figure out where am I wrong at.
Here is are native JavaScript Date functions, no need for an external library:
const getWeekNum = (date) => {
const janFirst = new Date(date.getFullYear(), 0, 1);
// Source: https://stackoverflow.com/a/27125580/3307678
return Math.ceil((((date.getTime() - janFirst.getTime()) / 86400000) + janFirst.getDay() + 1) / 7);
}
const isSameWeek = (dateA, dateB) => {
return getWeekNum(dateA) === getWeekNum(dateB);
}
const date1Str = '2023-02-05';
const date2Str = '2023-02-06';
const date3Str = '2023-02-12';
const dateSuffix = 'T00:00:00.000Z'; // or 'T00:00:00.000' for browserlocal time
const date1 = new Date(date1Str + dateSuffix);
const date2 = new Date(date2Str + dateSuffix);
const date3 = new Date(date3Str + dateSuffix);
console.log({
'date1': date1,
'date2': date2,
'date3': date3,
'getWeekNum(date1)': getWeekNum(date1),
'getWeekNum(date2)': getWeekNum(date2),
'getWeekNum(date3)': getWeekNum(date3),
'isSameWeek(date1, date2)': isSameWeek(date1, date2),
'isSameWeek(date1, date3)': isSameWeek(date1, date3),
});
Output:
{
"date1": "2023-02-05T00:00:00.000Z",
"date2": "2023-02-06T00:00:00.000Z",
"date3": "2023-02-12T00:00:00.000Z",
"getWeekNum(date1)": 6,
"getWeekNum(date2)": 6,
"getWeekNum(date3)": 7,
"isSameWeek(date1, date2)": true,
"isSameWeek(date1, date3)": false
}
Notes:
always provide a proper ISO 8601 format format for the new Date() constructor
use format YYY-MM-DDTHH:mm:ss.sssZ for UTC date
use format YYY-MM-DDTHH:mm:ss.sss for local browser date
If you have a date string variable of format YYY-MM-DD you need to append THH:mm:ss.sssZ or THH:mm:ss.sss to get the full ISO 8601 format

Get ISO date string based on month name

I have to create two ISO date strings in an Array based on the long month name.
Input: 'August'
Output: ['2020-08-01T00:00:00', '2020-08-31T00:00:00']
I am thinking about a switch case to check for each month but I am not sure how to create the ISO string with this information. I could match August with 08 and replace a pre-defined ISO string and replace it based on the input but this doesn't sound very clever.
You can get the month names from toLocaleString for the locale you are in or hardcode an array.
Then calculate the first of this month and the 0th of NEXT month
I had to normalise the time to 15:00 to handle timezones.
const yyyy = new Date().getFullYear();
const months = Array.from(Array(12).keys())
.map(month => new Date(yyyy, month, 5, 15, 0, 0, 0)
.toLocaleString('default', { month: 'long'}) );
const zeroTime = str => `${str.split("T")[0]}T00:00:00`;
const getDates = month => {
const monthNum = months.indexOf(month);
const start = new Date(yyyy, monthNum, 1, 15, 0, 0, 0),
end = new Date(yyyy, monthNum+1, 0, 15, 0, 0, 0)
return [zeroTime(start.toISOString()), zeroTime(end.toISOString())];
};
console.log(getDates("August"))
There are many ways to go about this, the only real issue is how to generate the list of month names. The following uses mplungian's approach of generating them in the browser default language, though I'm not sure that's a good idea.
The other part of the problem is to generate timestamps for the start and end of the month. That's pretty simple given a year and month number. You can use UTC values and toISOString, then trim the trailing Z to get local timestamps.
The following should be efficient as it only generates one date and array to get the month names, then one more of each on each call of getMonthDates. It also uses for loops instead of creating arrays and using array methods for iteration.
It also provides separate functions for getting the month number from the name and dates from month number and year. They use ECMAScript month number (0 = Jan, etc.) but could easily be converted to use calendar month number (1 = Jan, etc.).
// Given year and ECMAScript month number, return an array of ISO 8601
// formatted local timestamps for first and last days of the month
let getMonthDates = (monthNum = 0, year = new Date().getFullYear()) => {
let date = new Date(Date.UTC(year, monthNum));
let start = date.toISOString().substring(0, 19);
date.setUTCMonth(monthNum + 1, 0);
return [start, date.toISOString().substring(0, 19)];
}
// Given a month name, return it's ECMAScript month number
// Uses host default language for month name
let getMonthDatesFromName = (() => {
let date = new Date();
let monthNames = (() => {
date.setMonth(0, 1);
for (var arr=[], i=0; i<12; i++) {
arr.push(date.toLocaleString('default',{month:'long'}));
date.setMonth(i+1)
}
return arr;
})();
return (monthName, year) => {
let monthNum = monthNames.indexOf(monthName);
// If month name not found, return undefined
return monthNum < 0? void 0 : getMonthDates(monthNum, year);
}
})();
/** getMonthDatesFromName examples
*/
// Undefined if month name not valid
console.log('foo: ' + getMonthDatesFromName('foo'));
// Current month name
let monthName = new Date().toLocaleString('default',{month: 'long'});
console.log(monthName + ': ' + getMonthDatesFromName(monthName).toString());
// February, 2024
console.log('February, 2024: ' + getMonthDatesFromName('February', 2024).toString());
/** getMonthDates examples
*/
// January of current year by default
console.log('Default: ' + getMonthDates().toString());
// Month of current year by default, e.g. for April
console.log('April: ' + getMonthDates(3).toString());
// Month and year - February 2024
console.log('1, 2024: ' + getMonthDates(1, 2024).toString());

How to compare dates across timezones in JavaScript?

I'm trying to compare given date with current date, It is working fine for Indian timezone but other time zones getting one day off. I have went through similar type of issues and there suggestions are like convert UTC string. After converting UTC string getting correct date while console but when comparing not get correct result.
Here my given date in the format like 'YYYY-MM-DD'.
The initial comparison was like below, and this will work fine for Indian timezone.
const datestring = '2019-05-06';
const q = new Date();
const m = q.getMonth();
const d = q.getDate();
const y = q.getFullYear();
const currentDate = new Date(y, m, d);
const givenDate = new Date(datestring);
if (currentDate <= givenDate) {
return null;
} else {
return {
'currentDateChecker': true
};
}
}
The above one will work fine for Indian time zone and for some other time zone apart from Indian time zone, it is giving one day less.
But after converting to UTC like:
const givenDate = new Date(datestring).toUTCString();
Now this will give correct date but for comparing purpose I have converted both current date also to UTC string, by that time result is not coming as expected. I know there are number of articles existed related to this but not getting proper way so only posting this question.
The difficulty is that new Date() will create a date in YOUR timezone. For me, since I'm SAST (+2 hours), if I say new Date(2019, 4, 6) I will get the UTC datetime 5 May 22:00 2019. This makes it difficult to compare dates, since someone in India who wanted to compare "6 May 2019" will actually get a UTC date 6 May 2019, and that won't equal 5 May 2019.
Instead use Date.UTC(year, month, day) - an epoch time is number of milliseconds since 2970, Jan 1st in UTC.
const today = new Date()
const todayYear = today.getFullYear()
const todayMonth = today.getMonth()
const todayDay = today.getDate()
const todayUtc = Date.UTC(todayYear, todayMonth, todayDay)
const dateString = 'yyyy-mm-dd'
const dateArr = dateString.split('-')
const dateUtc = Date.UTC(dateArr[0], dateArr[1], dateArr[2])
if (todayUtc === dateUtc) {
// ...
}
You can use getTime to do the comparaison:
// ...
const currentDate = new Date(y, m, d).getTime();
const givenDate = new Date(datestring).getTime();
if (currentDate <= givenDate) {
return null;
} else {
return {
'currentDateChecker': true
};
}

Comparing Dates in NodeJS IF Statement

I am using nodejs/javascript and trying to compare two dates to each other in order to apply a specific style if the date is before the set date.
Here is what I have:
var d = new Date();
var date = d.getMonth()+1+'/'+d.getDate()+'/'+(d.getFullYear().toString().substr(-2)-1);
var da = new Date('1/4/18');
var da_test = da.getMonth()+1+'/'+da.getDate()+'/'+(da.getFullYear().toString().substr(-2));
if(da_test < date) {
// do something
}
date_test is currently returning the date from a year ago today, 1/23/18. I have set the other date that it will compare itself to, to 1/4/18. While this should be true, for some reason it is not whenever the IF statement runs. However, if I change the date to something like 1/2/18, then it returns true. How is that the case and how can it be changed so it will return true if it is any date before 1/23/18?
You can compare those two dates like this:
const d1 = new Date('1/23/18');
const d2 = new Date('1/4/18');
if (d2 < d1) ...
In your code example you are comparing two Strings
You can compare the milliseconds since epoch (the number of milliseconds since 1 January 1970 00:00:00)
const d1 = new Date('1/23/18');
const d2 = new Date('1/4/18');
if (d2.getTime() < d1.getTime()) {
}
You can also compare ISO date strings
const d1 = new Date('1/23/18');
const d2 = new Date('1/4/18');
if (d2.toISOString() < d1.toISOString()) {
}

Compare a date in string format with todays date

I know this has been asked before but I can't get it to work due to my date format, which I can't change. Any help would be appreciated.
My date is in this format;
4/11/2017 12:30 PM.
If I inspect it in the developer tools it shows it as
4/11/2017 12:30 PM EDIT: Won't show with prepended space here
i.e. with a space in front, not sure if that's relevant.
Does anyone know if it's possible or how to compare it with today's date to see if it's in the past or future?
I've tried tinkering with the following code but can't get it to work because of the time, PM, and forward slashes.
var q = new Date();
var m = q.getMonth();
var d = q.getDate();
var y = q.getFullYear();
var date = new Date(d,m,y);
mydate=new Date('13/04/2017');
console.log(date);
console.log(mydate)
if(date>mydate)
{
alert("greater");
}
else
{
alert("smaller")
}
If you have dates that are in the same format of something like 13/04/2017, you could split the string based on the slashes and compare the values starting from the right moving left.
By this, I mean when you have your array of three values for each date, you could first compare the year, if that's the same, move on to comparing the month, if that's the same then on to comparing the day.
But if for instance one of the year's is 2018 while the other is 2016, you would immediately know that the 2018 one comes later.
var st = "19/05/2019";
var st2 = "19/05/2019";
function provideLaterDate(date1, date2) {
var splitDateDate1 = date1.split("/").reverse();
var splitDateDate2 = date2.split("/").reverse();
var laterDate = false;
splitDateDate1.forEach(function(val, idx, arr) {
if ( laterDate === false ) {
if ( val > splitDateDate2[idx] ) {
laterDate = splitDateDate1;
} else if ( val < splitDateDate2[idx]) {
laterDate = splitDateDate2;
} else {
laterDate = "Both are the same";
}
}
});
if ( /\//.test(laterDate) ) {
return laterDate.reverse().join("/");
} else {
return laterDate;
}
}
To get rid of the "time pm" part, you could simply do something like:
// Assuming your date has a structure like this: 4/11/2017 12:30 PM.
var newDate = unformattedDate.split(" ")[0];
// This will separate your date string by spaces, and since there are no spaces until after the year in your date, the 0 index will give you the date minus the time and pm portion. Please pardon the not-consistent variable names.
The problem was with the way you were constructing date. Construct date like this var mydate = new Date(2017, 04, 03); and it works.
var q = new Date();
var m = q.getMonth();
var d = q.getDate();
var y = q.getFullYear();
var date = new Date(d, m, y);
var mydate = new Date(2017, 04, 03);
console.log(date);
console.log(mydate)
if (date > mydate) {
alert("greater");
}
else {
alert("smaller")
}
You can split the date. Be aware you should contruct your date as follows:
var date = new Date(y,m,d);
Means year first, then month and finally day, as you can see under https://www.w3schools.com/jsref/jsref_obj_date.asp
You can use the following code to perform what you want:
var q = new Date();
var m = q.getMonth();
var d = q.getDate();
var y = q.getFullYear();
var date = new Date(y,m,d);
newdate = '13/04/2017'
array = newdate.split('/');
var d1 = array[0]
var m1 = array[1]-1
var y1 = array[2]
mydate = new Date(y1,m1,d1);
console.log(date);
console.log(mydate)
if(date>mydate)
{
alert("greater");
}
else
{
alert("smaller")
}
You can always check the date created is correct by using the date.toString() function. Be aware 0=January for month as you can check under https://www.w3schools.com/jsref/jsref_getmonth.asp. That's why I added the -1 for var m1.
Problem:
It's not working because you are comparing a date with an Invalid date, it will always return false.
Explanation:
And the Invalid date comes from the line new Date('13/04/2017'), because 13 is expected to be a month number and not a day which is an invalid month, because the new Date(stringDate) will be treated as a local Date and not a UTC date by the browser, and it depends on which browser you are using.
You can see in the JavaScript Date Specification that:
parsing of date strings with the Date constructor (and Date.parse, they are equivalent) is strongly discouraged due to browser differences and inconsistencies. Support for RFC 2822 format strings is by convention only. Support for ISO 8601 formats differs in that date-only strings (e.g. "1970-01-01") are treated as UTC, not local.
Demo:
So if we change new Date('13/04/2017') to new Date('04/13/2017') the code will work as expected:
var date = new Date();
var mydate = new Date('04/13/2017');
console.log(date);
console.log(mydate)
if (date > mydate) {
alert("greater");
} else {
alert("smaller")
}
if(date.getTime()>mydate.getTime()){
alert("greater");
}
else if (date.getTime()==mydate.getTime){
alert("simmilar");
else {alert("smaller");}

Categories