0

I need to validade date yyyy-mm-dd on user keyup.

I'm currently at validating yyyy-mm with this Regex

^\d{0,4}$|^\d{4}[-]$|^\d{4}[-](0?[0-9]|1[012])$

JS Fiddle

But I need validade others part of date. Can anyone help me?

bobble bubble
  • 16,888
  • 3
  • 27
  • 46
LT001
  • 27
  • 1
  • 5
  • Can you show a [Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve) and clarify exactly what it is you don't understand? – M.T Mar 15 '16 at 11:08
  • A regular expression can't validate anything more than four digits, hyphen, two digits, hyphen, two digits. It can't determine whether the year is in a reasonable range, whether the month is in the range 01 through 12, or whether the date is in the month-length-dependent range of 01 to 28, 29, 30, or 31. – Steve Mar 15 '16 at 11:15
  • Your current more looks like it does *yyyy-mm* and not *yyyy-dd* – bobble bubble Mar 15 '16 at 11:26
  • Yes ,but i need yyy-mm-dd – LT001 Mar 15 '16 at 11:32
  • 1
    @Steve You could absolutely enumerate the valid dates to make sure the month is between 01 and 12 and even to make sure the day of month is in an expected range ... even for leap years if you like typing. – tripleee Mar 15 '16 at 11:34
  • 1
    Try [`^\d{0,4}$|^\d{4}-0?$|^\d{4}-(?:0?[1-9]|1[012])(?:-(?:0?[1-9]?|[12]\d|3[01])?)?$`](https://regex101.com/r/jB9lZ7/2). You want to validate while typing right? – bobble bubble Mar 15 '16 at 11:38
  • Is this , thank you @bobble – LT001 Mar 15 '16 at 11:42
  • welcome, just modified it a bit ([version 2](https://regex101.com/r/jB9lZ7/2)). – bobble bubble Mar 15 '16 at 11:44
  • @triplee, I see you are correct. My skills have been corrupted by too much Windows. However the expression by *bobble bubble* still doesn't understand month length; it appears that it will accept 2016-04-31 or 2015-02-29, for example. – Steve Mar 16 '16 at 07:58
  • 1
    @Steve Possible duplicate of [Regular Expression | Leap Years and More](http://stackoverflow.com/questions/8647893/regular-expression-leap-years-and-more) – tripleee Mar 16 '16 at 08:23
  • 1
    @Steve My regex is not to validate a full date but to check if the input characters while typed match the *yyyy-mm-dd* pattern (what was asked). Updated my answer to make it more clear : ) – bobble bubble Mar 16 '16 at 11:57

3 Answers3

4

Explanation: Vague checking input while typing if it matches the desired format yyyy-mm-dd.

Modified your current regex a bit and added the dd part so it becomes

^\d{0,4}$|^\d{4}-0?$|^\d{4}-(?:0?[1-9]|1[012])(?:-(?:0?[1-9]?|[12]\d|3[01])?)?$
  • (?: opens a non capture group for alternation
  • 0?[1-9]? optional 1-9 with preceding 0 or zero
  • [12]\d days 10-29
  • 3[01] days 30 and 31

See the demo at regex101

enter image description here


For dd-mm-yyyy try this variant:

^0?$|^(?:0?[1-9]|[12]\d|3[01])(?:-(?:(?:0$|0?[1-9]|1[012]?)(?:-\d{0,4})?)?)?$

Or for mm-dd-yyyy that one:

^0?$|^(?:0?[1-9]|1[012]?)(?:-(?:(?:0$|0?[1-9]|[12]\d|3[01])(?:-\d{0,4})?)?)?$

This does not actually validate a date (leap years/28-31 days). Just loose checks input while typing, you can probably make it shorter. As follows an example with the yyyy-mm-dd pattern.

$("#date").on("keyup", function()
{
    let valid = /^\d{0,4}$|^\d{4}-0?$|^\d{4}-(?:0?[1-9]|1[012])(?:-(?:0?[1-9]?|[12]\d|3[01])?)?$/.test(this.value), input = this.value;
    
    if(!valid) {
        this.value = input.substring(0, input.length - 1);
        this.style.backgroundColor = '#EEA39C';
    }
    setTimeout(() => { this.style.backgroundColor = '#88DD85'; }, 700);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="date" style="font-size: 20px" maxlength="10" type="text" />

To validate the full date when typed/submitted see this answer of @PhiLho and rearrange it to the desired format, e.g. for yyyy-mm-dd

function isValidDate(date)
{
    var matches = /^(\d{4})-(\d{1,2})-(\d{1,2})$/.exec(date);
    if (matches == null) return false;
    var y = matches[1];
    var m = matches[2] - 1;
    var d = matches[3];
    var composedDate = new Date(y, m, d);
    return composedDate.getDate() == d &&
            composedDate.getMonth() == m &&
            composedDate.getFullYear() == y;
}
<input type="text" id="date" style="font-size: 17px" value="2016-03-16">
<button onclick="alert(
  isValidDate(getElementById('date').value)
);" style="font-size: 17px">check date</button> 
bobble bubble
  • 16,888
  • 3
  • 27
  • 46
  • 1
    `2016-04-31` and `2016-02-31` is valid in your regex, which is wrong. – Ahsanul Haque Mar 15 '16 at 12:09
  • @AhsanulHaque Tried to clarify. It's just a loose check based on OP's regex while typing. It does not really validate a date. The full string should finally be checked if it is a valid date. – bobble bubble Mar 16 '16 at 11:48
  • @bobblebubble using the regex you shared here i was trying out for `dd-mm-yyyy` and `mm-dd-yyyy` formats, the first two digits on keypress its not validating to true, i am sure i missing out something silly here,. can please have a look and help me here.. `^(?:(?:0?[1-9]?|[12]\d|3[01])?)(?:-(?:0?[0-9]|1[012])?)(?:-(?:\d{0,4}|\d{4})?)?$` – mabiyan Mar 05 '22 at 10:09
  • 1
    @ashwathmabiyan Na, it needs refactoring. Just had some quick tries... [this one for `dd-mm-yyyy`](https://regex101.com/r/5bXhkG/1) and [another one for `mm-dd-yyyy`](https://regex101.com/r/BNMvy3/1) – bobble bubble Mar 06 '22 at 17:03
2

This regex is a bit complex, but check the whole Gregorian rule.

 regExp = "(((\d{2}(([13579][26])|([2468][480])|(0[48])))|(([13579][26])|([02468][480]))00)-02-29)|(\d{4}-((?:(0[13578]|1[02])-([0-2]\d|3[0-1]))|(?:(0[469]|11)-([0-2]\d|30))|(?:02-([0-1]\d|2[0-8]))))"
Ahsanul Haque
  • 10,676
  • 4
  • 41
  • 57
  • Your sulution validate full date, I need validate on user type a date. See link i add in my post. – LT001 Mar 15 '16 at 11:28
  • @Ahsanul Haque, does that check the whole Gregorian rule, or just the Julian? Even just the latter is quite impressive; one would hope that it's OK to incorrectly approve three days per four centuries. (A further complication for that question is that the Gregorian rule is not supposed to be used on dates before 1582, but that's not worth the bother for most purposes.) – Steve Mar 16 '16 at 08:10
  • @Steve, yes, it does check the whole Gregorian rule. – Ahsanul Haque Mar 16 '16 at 08:44
  • 2
    @Ahsanul Haque, wow, that's impressive. The complexity of the expression makes it difficult to tell without diagramming it out on paper (or asking). That suggests that a regular expression is the wrong tool for the job, unless the question is posed as a regular expression challenge, as opposed to a question of the best tool for the task. – Steve Mar 16 '16 at 08:55
  • (The tool for the task is to pass the input to a date parse function, as the link in @tripleee 's comment advises.) – Steve Mar 16 '16 at 08:59
0
var regExp = /^(\d{4})-(\d{2})-(\d{2})$/

regExp.test(value);
RIYAJ KHAN
  • 15,032
  • 5
  • 31
  • 53