Does anyone know of any way to check if strings are valid dates? I'm trying to block against invalid dates, while not forcing any kind of date format. Basically here's the problem:
!!Date.parse('hello 1') === true
Javascript can figure out a date from that string, therefore, it's a date. I'd rather it not be. Anyone?
How close would stripping out spaces around words get you? It at least weeds out "hello 1" and such.
Date.parse('hello 1'.replace(/\s*([a-z]+)\s*/i, "$1")); // NaN
Date.parse('jan 1'.replace(/\s*([a-z]+)\s*/i, "$1")); // Valid
[update]
Ok, so we'll just replace any non-alphanumerics that fall between a letter and a number:
replace(/([a-z])\W+(\d)/ig, "$1$2")
Since you're using moment.js, try using parsingFlags():
var m = moment("hello 1", ["YYYY/MM/DD"]).parsingFlags();
if (!m.score && !m.empty) {
// valid
}
It's the metrics used for isValid() and you can use them to make a stricter validation function.
Note: You can specify the other formats to support in the second argument's array.
Some other properties returned by parsingFlags() that might be of interest are the following:
m.unusedInput - Ex. ["hello "]
m.unusedTokens - Ex. ["MM", "DD"]
Use this function to check date
function isDate(s)
{
if (s.search(/^\d{1,2}[\/|\-|\.|_]\d{1,2}[\/|\-|\.|_]\d{4}/g) != 0)
return false;
s = s.replace(/[\-|\.|_]/g, "/");
var dt = new Date(Date.parse(s));
var arrDateParts = s.split("/");
return (
dt.getMonth() == arrDateParts[0]-1 &&
dt.getDate() == arrDateParts[1] &&
dt.getFullYear() == arrDateParts[2]
);
}
console.log(isDate("abc 1")); // Will give false
Working Fiddle
It would be ok if you check for several types of dates?
kind of this for narrow the permited dates:
if( givenDate.match(/\d\d\/\d\d\/\d\d\d\d/)
|| givenDate.match(/\w*? \d{1,2} \d{4}/)
|| givenDate.match(anotherFormatToMatch) )
UPDATED
Or, althougt it restrict characters, you coud use something like this:
function myFunction() {
var str = "The rain in SPAIN stays mainly in the plain";
var date = new Date(str);
if (date != "Invalid Date" && !isNaN(new Date(date) && !str.match(/a-z/g) )
alert(date);
}
Related
I have 2 dates. Both are in yyyy-mm-dd format. I applied a simple check that if
if ('2017-01-15' > '2016-12-15') {
return true;
} else {
return false;
}
But it is giving me a syntax error. What should I do?
Given the format of the date string and your code structure, what you have should be working. If you're getting an error, check that it's coming from the section of code you've shown in your question.
That being said, you can improve the code by changing the strings to Date objects before comparing them. You can also shorten the code by just returning the result of the comparison. Try this:
function dateComparison() {
return new Date('2017-01-15') > new Date('2016-12-15');
}
console.log(dateComparison());
As per the MDN
The return statement ends function execution and specifies a value to be returned to the function caller.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/return
So you must be getting this error if you are not using the if condition within a function.
Operators like ==, !=, ===, and !== require you to use date.getTime() like this:
var x = new Date('2017-01-15');
var y = new Date('2016-12-15');
var same = x.getTime() === y.getTime();
var notSame = x.getTime() !== y.getTime();
You could convert them to Date objects and then compare.
var dateStrA = "2017-01-15 00:00:00";
var dateStrB = "2016-12-15 00:00:00";
if (new Date(dateStrA) > new Date(dateStrB))
{
...
}
else
{
...
}
Comparing using equals, such as === will not work on Date objects. You can also use Date.compare()
You can use the moment.js library to help you achieve it:
return moment('2017-01-15').format('YYYY-MM-DD') > moment('2016-12-15').format('YYYY-MM-DD');
Try this...worked for me.
var startDate = "2019-03-23";
var endDate = "2019-03-24";
if(Date.parse(endDate) >= Date.parse(startDate)) {
console.log('endDate is greater');
} else {
console.log('startDate is greater');
}
You can try this
if(d1.getTime()>d2.getTime())
I need to do a date validation to accept it in dd/mm/yyyy format. However all conditions are working fine except that if I enter year of 6 digits it is also accepting it, like -
12/12/200000
as per my code is valid. Below is my code:
function validate(value) {
if(!value.match(/\d\d\/\d\d\/\d\d\d\d/))
return false;
return checkdate(value);
}
function checkdate(val)
{
var dates = val.split(/\D/);
if(dates[0] <= 0 || dates[0] > 31)
return false;
if(dates[1] <= 0 || dates[1] > 12)
return false;
var now = new Date(dates[2],dates[1]-1,dates[0]);
if (isNaN(now))
return false;
now.setHours(0,0,0,0);
if (now.getFullYear() == dates[2] && now.getMonth() + 1 == dates[1] && now.getDate() == dates[0])
return true;
return false;
}
I am not sure why it allowing year as 6 digits valid input?
The problem is in validate function, regular expression it matches against allows input values you don't want to pass as valid. Besides obvious dd/mm/yyyy format, it allows found text to be anywhere in string. Basically, you said for it to check "if there's said expression inside string", when it should have been "if the whole string matches this expression".
To fix the issue, add ^ at the beginning and $ at the end. ^ stands for string start and $ for string end:
/^\d\d\/\d\d\/\d\d\d\d$/
I think you would benefit from reading documentation on regular expression syntax used by JavaScript.
While at at, humans tend to have issues reading long repeating sequences of similar characters, like in your regexp. This expression is easer to understand and does exactly the same thing:
/^\d{2}\/\d{2}\/\d{4}$/
You're not limiting the regex with start and stop delimiters, so 12/12/200000 is a match as it matched the regex, and then some
if (!value.match(/^\d\d\/\d\d\/\d\d\d\d$/) )
As a sidenote, you don't have to type \d four times, you can do \d{4} to match four instances of \d
If you want to validate a date string by creating a Date object, you don't need to check the entire pattern, just create and Date and check the result. Do you really need two digits for day and month number?
If you want a 4 digit year, that must be checked separately as the constructor will happily convert two digit years to 20th century. If you really need two digit day and month, that can be checked at the same time as the year:
function validateDMY(s) {
var b = s.split(/\D/);
var d = new Date(b[2], --b[1], b[0]);
return d && /^\d{4}$/.test(b[2]) && b[1] == d.getMonth();
}
console.log(validateDMY('30/02/2015')); // false
console.log(validateDMY('30/22/2015')); // false
console.log(validateDMY('02/02/15')); // false
console.log(validateDMY('30/01/2015')); // true
I have a form where a user inserts the GPS coordinates of a location to a corresponding photo. Its easy enough to filter out invalid numbers, since I just have to test for a range of (-90, 90), (-180, 180) for lat/long coordinates.
However, this also means that regular text is valid input.
I've tried changing the test pattern to
var pattern= "^[a-zA-Z]"
and is used in the function to detect alphabetical characters
$(".lat").keyup(function(){
var thisID= this.id;
var num = thisID.substring(3, thisID.length);
var thisVal = $(this).val();
//if invalid input, show error message and hide save button
if (pattern.test(thisVal)){
$("#latError"+num).fadeIn(250);
$("#save"+num).fadeOut(100)
}
else { //otherwise, hide error message and show save
$("#save"+num).fadeIn(250);
$("#latError"+num).fadeOut(100);
}
});
However, this doesn't work as Firebug complains that pattern.test is not a function What would solve this issue?
This is what i use in my project:
const regexLat = /^(-?[1-8]?\d(?:\.\d{1,18})?|90(?:\.0{1,18})?)$/;
const regexLon = /^(-?(?:1[0-7]|[1-9])?\d(?:\.\d{1,18})?|180(?:\.0{1,18})?)$/;
function check_lat_lon(lat, lon) {
let validLat = regexLat.test(lat);
let validLon = regexLon.test(lon);
return validLat && validLon;
}
check_lat_lon(-34.11242, -58.11547) Will return TRUE if valid, else FALSE
I hope this will be usefull to you!
Do you need to use regex? Consider the following:
var val = parseFloat(lat);
if (!isNaN(val) && val <= 90 && val >= -90)
return true;
else
return false;
How about the pattern -?[0-9]{1,3}[.][0-9]+ then you parseInt and check the range as you said before.
test() is a method of the RegExp object - you're running it on a string, so will fail.
Enclose your pattern in a RegExp literal (/pattern/), so
var pattern= /^[a-zA-Z]/
That will get rid of the errors you're getting, but you have a separate issue with regards to a) whether your pattern is correct for what you want it to do; b) whether you need REGEX at all.
REGEX acts on strings - it cannot be used to determine whether a number is within a given range (unless that range is 0-10 inclusive).
#flem's answer shows the best way to approach what you're doing - no REGEX needed. The call to parseInt() will catch non-numeric characters since it will return NaN if the value contains any.
#paul flemming gave a great answer, this answer extends his and includes longitude and uses typescript.
I would suggest this in place of regex for speed and simplicity.
Since, parseFloat takes a string and returns a number isNaN check isn't needed. This function allows a string or a number and converts it to string for parseFloat and will then do the simple threshold tests against +-90 & +-180.
function isValidLatAndLong(lat: number |string, lon:number|string){
const num1 = "" +lat; //convert toString
const num2 = "" +lon;
if (parseFloat(num1) <= 90 && parseFloat(num1) >= -90 && parseFloat(num2) <= 180 && parseFloat(num2) >= -180){
return true;
}
else{
return false;
}
}
Anybody got any clue why this won't work with more than 1 date...
it only takes the first date in the array...
var unavailableDates = ["10-6-2011","13-6-2011"];
function unavailable(date) {
dmy = date.getDate() + "-" + (date.getMonth() + 1) + "-" + date.getFullYear();
if ($.inArray(dmy, unavailableDates) == 0) {
return [false, "", "Unavailable"];
} else {
var day = date.getDay();
return [(day != 0 && day != 2 && day != 3 && day != 4 && day != 6)];
}
}
see full example below
http://offline.raileisure.com/lee.php
Thanks in advance
Lee
It doesn't work because you're interpreting the return value of "$.inArray()" incorrectly. The function returns -1 when the search target cannot be found, and the index in the array when it can. Thus, when it returns 0, that means it did find what the code was looking for.
A cute trick — for those who like cute tricks — for checking the return value from functions like "$.inArray()" is to apply the "~" operator:
if (~$.inArray(needle, haystack)) {
// found it
}
else {
// did not find it
}
The "~" operator forms the bitwise complement (or "1's complement") of its argument. Because "~-1" is 0, and "~n" is non-zero for any other integer, it effectively converts the return value to a "truthy/falsy" value appropriately. Don't use it if you don't like cute tricks :-)
Also, that "dmy" variable used in a couple functions should be declared in each one with the var keyword.
jQuery.inArray returns the index of the item found, ie, when it matches the second value, it is returning 1, not the 0 you test for.
You should change your test to be >= 0 rather than == 0 when you do
if ($.inArray(dmy, unavailableDates) == 0) { ...
Is it reading it in as mm-dd-yyyy?
If so - then 13-6-2011 would not be a valid date.
Edit Okay - looking at your page; clearly not since 10th June is not available as expected.
I deleted the answer but where dates are concerned I think this is a valuable thing to remember (e.g. on a US client presumably I'd be right?) so I undeleted it.
I'll get rid of it again though if the community feels I should.
Try this:
in pure javascript:
I made some modifications to make your code faster
function inArrayOrStr (o, v) {
return ~o.indexOf(v);
}
unavailableDates = ["10-6-2011","13-6-2011"];
function unavailable(date) {
var dmy = [date.getDate() ,(date.getMonth() + 1) , date.getFullYear()].join("-");
if (inArrayOrStr(unavailableDates, dmy) {
return [false, "", "Unavailable"];
} else {
var day = date.getDay();
return [day > 7];
}
}
I have some code for validating date below:
function validateForm() {
var errFound = 0;
//var patt_date = new RegExp("^((((19|20)(([02468][048])|([13579][26]))-02-29))|((20[0-9][0-9])|(19[0-9][0-9]))-((((0[1-9])|(1[0-2]))-((0[1-9])|(1\d)|(2[0-8])))|((((0[13578])|(1[02]))-31)|(((0[1,3-9])|(1[0-2]))-(29|30)))))$");
var patt_date = new RegExp("^[0-9]{4}-(((0[13578]|(10|12))-(0[1-9]|[1-2][0-9]|3[0-1]))|(02-(0[1-9]|[1-2][0-9]))|((0[469]|11)-(0[1-9]|[1-2][0-9]|30)))$");
if (patt_date.test(document.getElementById("datefrom").value) == false){errFound = errFound + 1;document.getElementById("datefrom").className = "error";}
if (errFound > 0)
alert('Please correct red colored field!');
else
return true;
return false;
}
Above code should work with YYYY-MM-DD format, but fail to validate date such as "2009-02-29"
The commented code should work (//var patt_date = new RegExp...), it can catch "2009-02-29", but it ruin the validation when i put invalid data and try to correct it, it keeps complain there something wrong with form value after i had correct them (especially on form with multiple input)
Maybe someone can fix the current regex?
Edited, what i want just a simple replacement for above regexp, mean a new regexp pattern not the whole new method to validate date
And for reference, i simply grab the regexp pattern from:
http://www.regexlib.com/REDetails.aspx?regexp_id=694 and
http://www.regexlib.com/REDetails.aspx?regexp_id=933
Tested with 2009-02-29, 1st link work & 2nd not. Again the problem was only the 2nd regexp didn't detect value 2009-02-29 as invalid while 1st can (but it ruin my code? so it's must be there something wrong with it).
Thanks,
Dels
Don't do the whole date validation with a regular expression, that's really pushing the limits of what regexps were designed for. I would suggest this procedure instead:
Check date against regexp /^\d{4}-\d{2}-\d{2}$/
Extract year, month, and day using substr() and convert to integers
Use some if statements to validate the integers. Like so:
if (month == 2) {
if (day == 29) {
if (year % 4 != 0 || year % 100 == 0 && year % 400 != 0) {
// fail
}
}
else if (day > 28) {
// fail
}
}
else if (month == 4 || month == 6 || month == 9 || month == 11) {
if (day > 30) {
// fail
}
}
else {
if (day > 31) {
// fail
}
(That could certainly be written more concisely) Alternatively, you could probably perform this validation using Javascript's Date class - you might have to do something like parsing the date, converting it back to a string, and checking if the two strings are equal. (I'm not a Javascript expert)
I kinda agree with David on this... Regex matches should not be used as an exclusive criterion to decide if the passed date is, in fact, valid. The usual procedure in Javascript validation involves a few steps :
a. The first step is to ensure that the passed string matches expected date formats by matching it against a Regex. The following may be a stricter Regex pattern.
// Assuming that the only allowed separator is a forward slash.
// Expected format: yyyy-mm-dd
/^[12][90][\d][\d]-[0-3]?[\d]-[01]?[\d]$/
b. The second step is to parse the string into a Date object which returns the no. of milliseconds since 1970. Use this number as a parameter for the Date constructor.
c. Since JS automatically rolls over the passed date to the nearest valid value, you still cannot be certain if the Date object created matches that which was passed. To determine if this happened, the best way is to split the passed string according to the separator and compare individual date components:
// d is the created Date object as explained above.
var arrDateParts = inputDate.split("-");
if ((d.getFullYear() == arrDateParts[0]) && (d.getMonth() == arrDateParts[1]) && (d.getDate() == arrDateParts[2]))
return true;
else
return false;
This javascript code validates date exactly. You can copy it and test it in your browser.
var regDate = '^(19[0-9]{2}|2[0-9]{3})-(0[1-9]{1}|1[0-2]{1}){1}-(0[1-9]|(1|2)[0-9]|3[0-1]){1}$';
var txt='2010-01-31';
if(txt.match(regDate))
{
alert('date match');
}