Is there any way to have a regex in JavaScript that validates dates of multiple formats, like: DD-MM-YYYY or DD.MM.YYYY or DD/MM/YYYY etc? I need all these in one regex and I'm not really good with it. So far I've come up with this: var dateReg = /^\d{2}-\d{2}-\d{4}$/;
for DD-MM-YYYY. I only need to validate the date format, not the date itself.

- 6,514
- 16
- 85
- 137
-
1You might be interested in http://www.datejs.com/ – Py. Sep 12 '11 at 12:42
-
If the only thing that varies is the separator then replace the `-` with `[\-\/\.]` (or whatever the escaping would be). – Dave Newton Sep 12 '11 at 12:42
-
It's your own custom format date string. International formats is: dd.mm.yyyy or mm/dd/yyyy or yyyy-mm-dd. – Andrew D. Sep 12 '11 at 13:27
-
This is the BEST answer, no ugly Regex and such: http://stackoverflow.com/questions/5774931/javascript-regular-expression-to-validate-date/5775146#5775146 – vsync Nov 14 '11 at 13:14
-
Please consider reassigning the correct answer. Current answer matches incorrect dates (99-99-9999, etc..). Thanks! – Dropout Dec 09 '15 at 07:40
-
@Dropout I've instead edited the question, to specify that I only needed to validate the format, not the actual date validity. If that were the case, @nicoabie's answer would have been better, even though it says `01.01-2015` is valid, so none of the answers correctly fully validate a date. Thanks for pointing this out, though. – Eduard Luca Dec 09 '15 at 11:01
-
1@EduardLuca OK great, thank you too! just trying to make things more helpful for others which come to the question later ;) cheers! – Dropout Dec 09 '15 at 12:14
11 Answers
You could use a character class ([./-]
) so that the seperators can be any of the defined characters
var dateReg = /^\d{2}[./-]\d{2}[./-]\d{4}$/
Or better still, match the character class for the first seperator, then capture that as a group ([./-])
and use a reference to the captured group \1
to match the second seperator, which will ensure that both seperators are the same:
var dateReg = /^\d{2}([./-])\d{2}\1\d{4}$/
"22-03-1981".match(dateReg) // matches
"22.03-1981".match(dateReg) // does not match
"22.03.1981".match(dateReg) // matches

- 57,113
- 24
- 136
- 237
-
1thanks. other than the slash "/" not being escaped correctly, it works fine. – Eduard Luca Sep 12 '11 at 12:57
-
I don't think the slash needs to be escaped inside a character class, but there is no harm in escaping it if you want to. Might make the syntax hilighting in your text editor work better, but should work either way. – Billy Moon Sep 12 '11 at 13:02
-
can you add a limitation for the first number (month) not to be over '3'? – vsync Nov 13 '11 at 10:03
-
-
or simply you can use this https://www.npmjs.com/package/raysk-vali for date validation and more. – Ravi Singh Jan 15 '20 at 11:44
Format, days, months and year:
var regex = /^(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](19|20)\d\d$/;

- 28,421
- 8
- 67
- 102

- 2,684
- 1
- 20
- 19
-
This partially validates the date, but still allows for dates like `30-02-2013` which is invalid. More complex rules are needed to account for different month lengths. – Billy Moon Mar 18 '13 at 11:44
-
3Technically speaking @BillyMoon, we are actually validating its format, not the date itself. Yours allows dates like 30-02-2013 too my friend. – nicoabie Mar 18 '13 at 20:03
-
Yes, mine is designed to extract the numbers from valid dates, and does not attempt to do validation, which yours does. I think with some adjustment, you could have reasonable validation of dates, which I would like to see you do, but half validating them seems to me like having a weak fence on a cliff edge, better to have none at all, lest someone leans on it! Better still to have a strong one. – Billy Moon Mar 18 '13 at 20:25
-
@BillyMoon `Format, days, months and year:`, what are you talking about? – Dropout Dec 09 '15 at 08:33
-
-
@BillyMoon oh, sorry I thought you were talking about MM-DD-YYYY being an invalid format, now I noticed it's 30th Feb. My bad, sorry. – Dropout Dec 10 '15 at 06:28
The suggested regex will not validate the date, only the pattern.
So 99.99.9999 will pass the regex.
You later specified that you only need to validate the pattern but I still think it is more useful to create a date object
const isDDMMYYYY = str => {
let [dd, mm, yyyy] = str.split(/[\.\-\/]/); // change to suit your locale
dd = +dd; // cast to number
yyyy = +yyyy; // cast to number
let mm0 = mm - 1, // js months are 0 based
date = new Date(yyyy, mm0, dd, 15, 0, 0, 0); // normalise
return mm0 === date.getMonth() && dd === date.getDate() && yyyy === date.getFullYear();
};
const dates = [
"13-01-2023",
"13.01.2023",
"13/01/2023",
"08-08-1991",
"29/02/2011"
];
dates.forEach(date => console.log(date, ':', isDDMMYYYY(date)));

- 169,008
- 28
- 173
- 236
-
the validation of invalid date values will be done by me manually. if i enter something like 08-08-1991 with your solution, would get me an "Invalid Date" in javascript for some reason. – Eduard Luca Sep 12 '11 at 12:59
-
1Not in Fx : I added that date to http://jsfiddle.net/mplungjan/Mqh8D/ What browser are you one? – mplungjan Sep 12 '11 at 19:43
-
If you use parseInt you MUST use the radix 10 since 08 and 09 are invalid octal numbers – mplungjan Sep 28 '12 at 16:07
-
Why do you increment and decrement the months ? See: `var date = new Date(yyyy,mm-1,dd,0,0,0,0);` (`(date.getMonth()+1)`) – Ndrslmpk May 17 '22 at 11:13
-
Js months are 0 based - I can decrement the month in the constructor or increment in the comparison – mplungjan May 17 '22 at 11:17
You can use regular multiple expressions with the use of OR (|) operator.
function validateDate(date){
var regex=new RegExp("([0-9]{4}[-](0[1-9]|1[0-2])[-]([0-2]{1}[0-9]{1}|3[0-1]{1})|([0-2]{1}[0-9]{1}|3[0-1]{1})[-](0[1-9]|1[0-2])[-][0-9]{4})");
var dateOk=regex.test(date);
if(dateOk){
alert("Ok");
}else{
alert("not Ok");
}
}
Above function can validate YYYY-MM-DD, DD-MM-YYYY date formats. You can simply extend the regular expression to validate any date format. Assume you want to validate YYYY/MM/DD, just replace "[-]" with "[-|/]". This expression can validate dates to 31, months to 12. But leap years and months ends with 30 days are not validated.

- 10,450
- 8
- 41
- 52
Make use of brackets /^\d{2}[.-/]\d{2}[.-/]\d{4}$/
http://download.oracle.com/javase/tutorial/essential/regex/char_classes.html

- 860
- 7
- 23
Please find in the below code which enables to perform the date validation for any of the supplied format or based on user locale to validate start/from and end/to dates. There could be some better approaches but have come up with this. Have tested it for the formats like: MM/dd/yyyy, dd/MM/yyyy, yyyy-MM-dd, yyyy.MM.dd, yyyy/MM/dd and dd-MM-yyyy.
Note supplied date format and date string go hand in hand.
<script type="text/javascript">
function validate(format) {
if(isAfterCurrentDate(document.getElementById('start').value, format)) {
alert('Date is after the current date.');
} else {
alert('Date is not after the current date.');
}
if(isBeforeCurrentDate(document.getElementById('start').value, format)) {
alert('Date is before current date.');
} else {
alert('Date is not before current date.');
}
if(isCurrentDate(document.getElementById('start').value, format)) {
alert('Date is current date.');
} else {
alert('Date is not a current date.');
}
if (isBefore(document.getElementById('start').value, document.getElementById('end').value, format)) {
alert('Start/Effective Date cannot be greater than End/Expiration Date');
} else {
alert('Valid dates...');
}
if (isAfter(document.getElementById('start').value, document.getElementById('end').value, format)) {
alert('End/Expiration Date cannot be less than Start/Effective Date');
} else {
alert('Valid dates...');
}
if (isEquals(document.getElementById('start').value, document.getElementById('end').value, format)) {
alert('Dates are equals...');
} else {
alert('Dates are not equals...');
}
if (isDate(document.getElementById('start').value, format)) {
alert('Is valid date...');
} else {
alert('Is invalid date...');
}
}
/**
* This method gets the year index from the supplied format
*/
function getYearIndex(format) {
var tokens = splitDateFormat(format);
if (tokens[0] === 'YYYY'
|| tokens[0] === 'yyyy') {
return 0;
} else if (tokens[1]=== 'YYYY'
|| tokens[1] === 'yyyy') {
return 1;
} else if (tokens[2] === 'YYYY'
|| tokens[2] === 'yyyy') {
return 2;
}
// Returning the default value as -1
return -1;
}
/**
* This method returns the year string located at the supplied index
*/
function getYear(date, index) {
var tokens = splitDateFormat(date);
return tokens[index];
}
/**
* This method gets the month index from the supplied format
*/
function getMonthIndex(format) {
var tokens = splitDateFormat(format);
if (tokens[0] === 'MM'
|| tokens[0] === 'mm') {
return 0;
} else if (tokens[1] === 'MM'
|| tokens[1] === 'mm') {
return 1;
} else if (tokens[2] === 'MM'
|| tokens[2] === 'mm') {
return 2;
}
// Returning the default value as -1
return -1;
}
/**
* This method returns the month string located at the supplied index
*/
function getMonth(date, index) {
var tokens = splitDateFormat(date);
return tokens[index];
}
/**
* This method gets the date index from the supplied format
*/
function getDateIndex(format) {
var tokens = splitDateFormat(format);
if (tokens[0] === 'DD'
|| tokens[0] === 'dd') {
return 0;
} else if (tokens[1] === 'DD'
|| tokens[1] === 'dd') {
return 1;
} else if (tokens[2] === 'DD'
|| tokens[2] === 'dd') {
return 2;
}
// Returning the default value as -1
return -1;
}
/**
* This method returns the date string located at the supplied index
*/
function getDate(date, index) {
var tokens = splitDateFormat(date);
return tokens[index];
}
/**
* This method returns true if date1 is before date2 else return false
*/
function isBefore(date1, date2, format) {
// Validating if date1 date is greater than the date2 date
if (new Date(getYear(date1, getYearIndex(format)),
getMonth(date1, getMonthIndex(format)) - 1,
getDate(date1, getDateIndex(format))).getTime()
> new Date(getYear(date2, getYearIndex(format)),
getMonth(date2, getMonthIndex(format)) - 1,
getDate(date2, getDateIndex(format))).getTime()) {
return true;
}
return false;
}
/**
* This method returns true if date1 is after date2 else return false
*/
function isAfter(date1, date2, format) {
// Validating if date2 date is less than the date1 date
if (new Date(getYear(date2, getYearIndex(format)),
getMonth(date2, getMonthIndex(format)) - 1,
getDate(date2, getDateIndex(format))).getTime()
< new Date(getYear(date1, getYearIndex(format)),
getMonth(date1, getMonthIndex(format)) - 1,
getDate(date1, getDateIndex(format))).getTime()
) {
return true;
}
return false;
}
/**
* This method returns true if date1 is equals to date2 else return false
*/
function isEquals(date1, date2, format) {
// Validating if date1 date is equals to the date2 date
if (new Date(getYear(date1, getYearIndex(format)),
getMonth(date1, getMonthIndex(format)) - 1,
getDate(date1, getDateIndex(format))).getTime()
=== new Date(getYear(date2, getYearIndex(format)),
getMonth(date2, getMonthIndex(format)) - 1,
getDate(date2, getDateIndex(format))).getTime()) {
return true;
}
return false;
}
/**
* This method validates and returns true if the supplied date is
* equals to the current date.
*/
function isCurrentDate(date, format) {
// Validating if the supplied date is the current date
if (new Date(getYear(date, getYearIndex(format)),
getMonth(date, getMonthIndex(format)) - 1,
getDate(date, getDateIndex(format))).getTime()
=== new Date(new Date().getFullYear(),
new Date().getMonth(),
new Date().getDate()).getTime()) {
return true;
}
return false;
}
/**
* This method validates and returns true if the supplied date value
* is before the current date.
*/
function isBeforeCurrentDate(date, format) {
// Validating if the supplied date is before the current date
if (new Date(getYear(date, getYearIndex(format)),
getMonth(date, getMonthIndex(format)) - 1,
getDate(date, getDateIndex(format))).getTime()
< new Date(new Date().getFullYear(),
new Date().getMonth(),
new Date().getDate()).getTime()) {
return true;
}
return false;
}
/**
* This method validates and returns true if the supplied date value
* is after the current date.
*/
function isAfterCurrentDate(date, format) {
// Validating if the supplied date is before the current date
if (new Date(getYear(date, getYearIndex(format)),
getMonth(date, getMonthIndex(format)) - 1,
getDate(date, getDateIndex(format))).getTime()
> new Date(new Date().getFullYear(),
new Date().getMonth(),
new Date().getDate()).getTime()) {
return true;
}
return false;
}
/**
* This method splits the supplied date OR format based
* on non alpha numeric characters in the supplied string.
*/
function splitDateFormat(dateFormat) {
// Spliting the supplied string based on non characters
return dateFormat.split(/\W/);
}
/*
* This method validates if the supplied value is a valid date.
*/
function isDate(date, format) {
// Validating if the supplied date string is valid and not a NaN (Not a Number)
if (!isNaN(new Date(getYear(date, getYearIndex(format)),
getMonth(date, getMonthIndex(format)) - 1,
getDate(date, getDateIndex(format))))) {
return true;
}
return false;
}
Below is the HTML snippet
<input type="text" name="start" id="start" size="10" value="05/31/2016" />
<br/>
<input type="text" name="end" id="end" size="10" value="04/28/2016" />
<br/>
<input type="button" value="Submit" onclick="javascript:validate('MM/dd/yyyy');" />

- 569
- 7
- 5
@mplungjan, @eduard-luca
function isDate(str) {
var parms = str.split(/[\.\-\/]/);
var yyyy = parseInt(parms[2],10);
var mm = parseInt(parms[1],10);
var dd = parseInt(parms[0],10);
var date = new Date(yyyy,mm-1,dd,12,0,0,0);
return mm === (date.getMonth()+1) &&
dd === date.getDate() &&
yyyy === date.getFullYear();
}
new Date() uses local time, hour 00:00:00 will show the last day when we have "Summer Time" or "DST (Daylight Saving Time)" events.
Example:
new Date(2010,9,17)
Sat Oct 16 2010 23:00:00 GMT-0300 (BRT)
Another alternative is to use getUTCDate().

- 343
- 2
- 6
To make sure it will work, you need to validate it.
function mmIsDate(str) {
if (str == undefined) { return false; }
var parms = str.split(/[\.\-\/]/);
var yyyy = parseInt(parms[2], 10);
if (yyyy < 1900) { return false; }
var mm = parseInt(parms[1], 10);
if (mm < 1 || mm > 12) { return false; }
var dd = parseInt(parms[0], 10);
if (dd < 1 || dd > 31) { return false; }
var dateCheck = new Date(yyyy, mm - 1, dd);
return (dateCheck.getDate() === dd && (dateCheck.getMonth() === mm - 1) && dateCheck.getFullYear() === yyyy);
};
If you want to validate your date(YYYY-MM-DD)
along with the comparison it will be use full for you...
function validateDate()
{
var newDate = new Date();
var presentDate = newDate.getDate();
var presentMonth = newDate.getMonth();
var presentYear = newDate.getFullYear();
var dateOfBirthVal = document.forms[0].dateOfBirth.value;
if (dateOfBirthVal == null)
return false;
var validatePattern = /^(\d{4})(\/|-)(\d{1,2})(\/|-)(\d{1,2})$/;
dateValues = dateOfBirthVal.match(validatePattern);
if (dateValues == null)
{
alert("Date of birth should be null and it should in the format of yyyy-mm-dd")
return false;
}
var birthYear = dateValues[1];
birthMonth = dateValues[3];
birthDate= dateValues[5];
if ((birthMonth < 1) || (birthMonth > 12))
{
alert("Invalid date")
return false;
}
else if ((birthDate < 1) || (birthDate> 31))
{
alert("Invalid date")
return false;
}
else if ((birthMonth==4 || birthMonth==6 || birthMonth==9 || birthMonth==11) && birthDate ==31)
{
alert("Invalid date")
return false;
}
else if (birthMonth == 2){
var isleap = (birthYear % 4 == 0 && (birthYear % 100 != 0 || birthYear % 400 == 0));
if (birthDate> 29 || (birthDate ==29 && !isleap))
{
alert("Invalid date")
return false;
}
}
else if((birthYear>presentYear)||(birthYear+70<presentYear))
{
alert("Invalid date")
return false;
}
else if(birthYear==presentYear)
{
if(birthMonth>presentMonth+1)
{
alert("Invalid date")
return false;
}
else if(birthMonth==presentMonth+1)
{
if(birthDate>presentDate)
{
alert("Invalid date")
return false;
}
}
}
return true;
}
Don't re-invent the wheel. Use a pre-built solution for parsing dates, like http://www.datejs.com/

- 9,994
- 3
- 29
- 31
-
3the reason i don't want to add an external library is that it's not necessary, it would only make the site load slower. but yes, that would have been a solution – Eduard Luca Sep 12 '11 at 12:58