Regex validation grails date-like format

2.1k Views Asked by At

Im currently working in a grails project and I ended up to a problem regarding matches constraints in grails. My field should only accept a String with a date-like format exactly like this:

10-25-2012 5:00PM

Is this possible in matches constraint using regex? I'm always having a hard time in data filtering using regex cause it's a little bit confusing.

4

There are 4 best solutions below

0
On

Is there no Date object you can use? I don't know, but I can help you with the regex:

Constructing a regex is not difficult and especially in your case straight forward:

^\d{2}-\d{2}-\d{4} \d{2}:\d{2}[AP]M$

^ Matches the start of the string

$ Matches the end of the string

\d is a digit

{2} is a quantifier that makes the previous character required 2 times

[AP] is a character class that matches A or P

This regex just checks the format, not if the digits represent a valid Date or Time! (e.g. 99-99-0000 35:61PM is valid)

Read my Blog post What absolutely every Programmer should know about regular expressions for some more brief information.

1
On

Try this one: ^(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])-((?:19|20)\d\d) ([0-1]?[0-9]|2[0-4]):([0-5][0-9])(?::([0-5][0-9]))?(AM|PM)$

^ Start of string
    (0[1-9]|1[012]) Month
    -
    (0[1-9]|[12][0-9]|3[01]) Day
    -
    ((?:19|20)\d\d) Year

    ([0-1]?[0-9]|2[0-4]) HH
    :
    ([0-5][0-9]) MM
    (?::([0-5][0-9]))? optional :SS
    (AM|PM)
$ End of string

It captures month, day, year, hours, minutes, seconds and AM/PM.

Edit: As Vikas points out it does not check how many days a month can have.

0
On

If it's a data, why not to validate it using standard date formatter? Like:

static constraints = {
   mydate validator: {
      try {
         Date.parse('MM-dd-yyyy hh:mma', it)
         return true
      } catch (ParseException e) {
         return false
      }
   }
}

Btw, at this case Date can parse not so valid dates (and transform it to correnct value, like 15am to 3pm). If you need exactly valid format, your can compare it with original value:

static constraints = {
   mydate validator: {
      try {
         Date date = Date.parse('MM-dd-yyyy hh:mma', it)
         return Date.format('MM-dd-yyyy hh:mma', date) == it
      } catch (ParseException e) {
         return false
      }
   }
}

Or you can use SimpleDateFormat instead:

final static DateFormat DATEFORMAT = new SimpleDateFormat('MM-dd-yyyy hh:mma') 

static constraints = {
   mydate validator: {
      try {
         Date date = DATEFORMAT.parse(it)
         return DATEFORMAT.format(date) == it
      } catch (ParseException e) {
         return false
      }
   }
}
0
On

Try this

\b(?:(?:(?:0?[469]|11)\-(?:0?(?:[1-9]|[12][0-9])|30)\-(?:1[7-9][0-9]{2}|200[0-9]|201[0-2]))|(?:(?:0?[13578]|1[02])\-(?:0?(?:[1-9]|[12][0-9])|3[01])\-(?:1[7-9][0-9]{2}|200[0-9]|201[0-2]))|(?:(?:0?2)\-(?:0?(?:[1-9]|1[0-9])|2[0-8])\-(?:1[7-9][0-9]{2}|200[0-9]|201[0-2]))) +(?:(?:(?:0?([0-9])|1[0-2])):(?:0?([0-9])|[1-5][0-9])(?:[AP]M))\b

or

\b(?:(?:(?:0?[469]|11)\-(?:0?(?:[1-9]|[12][0-9])|30)\-(?:1[7-9][0-9]{2}|200[0-9]|201[0-2]))|(?:(?:0?[13578]|1[02])\-(?:0?(?:[1-9]|[12][0-9])|3[01])\-(?:1[7-9][0-9]{2}|200[0-9]|201[0-2]))|(?:(?:0?2)\-(?:0?(?:[1-9]|1[0-9])|2[0-9])\-(?:1[7-9][0-9]{2}|200[0-9]|201[0-2]))) +(?:(?:(?:0?([0-9])|1[0-2])):(?:0?([0-9])|[1-5][0-9])(?:[AP]M))\b

Note: Two patterns both have a common limitation that it would match invalid dates if the month is february. If-else conditionals are accepted in some RegEx flavors but there is no such functions exist for arithmatic operations. May be in far or near future this could be implemented in some RegEx flavors, but I think this not the case for what RegEx is basically is.

  1. First pattern would not find any date greater than 28 from month of February. And it would never match any invalid date.
  2. Second is exactly the same as above, but for it the number is 29.

And I am well-known about the fact that this issue could not entirely solved by using RegEx.