Advanced Date Matching with Regex - 2 methods to validate

Written by Paul Ogier

16th Jul 2020

Are you looking to do an advanced date matching and validation with Regular Expressions? Are you trying to make sure that your validation takes into account months with 30 and 31 days, and that pesky February who has 28 days and then every 4 years it has 29 days?!

Resources for Advanced Date Matching with Regex

https://regex101.com/r/9JIyQs/2 - Simple Example
https://www.debuggex.com/ - Regex Visualizer
https://jex.im/regulex/#!flags=&re=%5E(a%7Cb)*%3F%24 - Another Regex Visualizer
https://taming.tech/Google-Doc-Regex-Planning Thinking behind the Regex for a Date
https://regex101.com/r/YSSP9v/1 - Full Regex for date
https://regex101.com/r/YSSP9v/2 - Blank for you to start with
https://regex101.com/r/YSSP9v/3 - My completed example after demo

About this Regex Tutorial

Using 2 different examples of how to validate months using Regex, we break down this complexity for you into bite size chunks. We go through the whole process from scratch and show you the thinking in how to formulate your expressions.

One of the biggest difficulties with working on a new expression is being able to see where you have gone wrong and then troubleshooting the expressions. We use a Regex Visualiser to show us and you how it works. How the validation goes from 1 side of the Regular Expression and gets thrown out of each leg and is only valid in one place.

In this tutorial we start with a simple example of how to validate against date entries. The problem with this Regex is that if you are looking to reject inputs that might be incorrect like 30/Feb/2001 then this will not stop those from being entered.

Simple Date Matching

(?<MM>[01]?[0-9])\/(?<DD>[0-3]?[0-9])\/(?<YYYY>[0-2][0-9][0-9][0-9])

You can do your own tests here https://regex101.com/r/9JIyQs/2 this is based on the MM/DD/YYYY format

If you look at the examples from this website https://www.regular-expressions.info/dates.html you will see that they start with this example.

^(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$

You can see their code working here https://regex101.com/r/9ec0Ko/1 This still doesn't validate for months working on different days per month or leap years. They do however continue on to validate the dates using Perl code. This is in the yyyy-mm-dd format from 1900-01-01 through 2099-12-31.

sub isvaliddate {
  my $input = shift;
  if ($input =~ m!^((?:19|20)\d\d)[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$!) {
    # At this point, $1 holds the year, $2 the month and $3 the day of the date entered
    if ($3 == 31 and ($2 == 4 or $2 == 6 or $2 == 9 or $2 == 11)) {
      return 0; # 31st of a month with 30 days
    } elsif ($3 >= 30 and $2 == 2) {
      return 0; # February 30th or 31st
    } elsif ($2 == 2 and $3 == 29 and not ($1 % 4 == 0 and ($1 % 100 != 0 or $1 % 400 == 0))) {
      return 0; # February 29th outside a leap year
    } else {
      return 1; # Valid date
    }
  } else {
    return 0; # Not a date
  }
}

That is fine for their example, but for me, I want to have my validation all in one line that can be adapted for Python, PHP, PowerShell etc and this doesn't work for me.

So we start with a very complex looking expression. If you are happy to just copy and paste then you can use this. But if you want to learn how to do this, then please watch the video.

^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]|(?:Jan|Mar|May|Jul|Aug|Oct|Dec)))\1|(?:(?:29|30)(\/|-|\.)(?:0?[1,3-9]|1[0-2]|(?:Jan|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec))\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)(?:0?2|(?:Feb))\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9]|(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep))|(?:1[0-2]|(?:Oct|Nov|Dec)))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$

Check it out here https://regex101.com/r/YSSP9v/1 We have used the UK and South African date format here of DD/MM/YYYY. You can obviously update this to the international date format of YYYY/MM/DD.

After going through the validation and showing you how to work and troubleshoot your validation, I finished on this expression, which I actually like more than my original example.

^(?<Monthswith31>31(?<s1>\/|\.|-)(0?[13578]|1[02]|(Jan|Mar|May|Jul|Aug|Oct|Dec))\g<s1>(?<Year>19[0-9][0-9]|200[0-7]))$|^(?<Monthswith29or30>(29|30)(?<s2>\/|\.|-)(0?[1,3-9]|1[0-2]|(Jan|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec))\g<s2>(?<Year2>19[0-9][0-9]|200[0-7]))$|^(?<Allmonthswith28>(0?[1-9]|1[0-9]|2[0-8])(?<s3>\/|\.|-)(0?[1-9]|1[0-2]|(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec))\g<s3>(?<Year3>19[0-9][0-9]|200[0-7]))$|^(?<FebLeapYears>29(?<s4>\/|\.|-)(0?2|Feb)\g<s4>(19([02468][048]|[13579][26])|200[04]))$

You can play and test it for yourself here https://regex101.com/r/YSSP9v/3

We have worked with 4 "legs" in this Regex. One to validate with all months with 31 days, so that would be Jan, Mar, May, Jul, Aug, Oct, Dec. Then we look at all months with 29 or 30 days, so that would be Jan, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec. Then all the months with 1-28 days so that is all months. And then finally we look at leap years and then that would be Feb 29 in years like 1996, 2000, 2004 etc and we play with a easy way to figure out what the year would validate against.

This video might be an hour long, but it shows my logic and thinking and how to figure out any Regex that you would like to play with.

Udemy Regex Course

Taming REGEX Regular Expressions on Udemy

This tutorial is a part of a Regex course on Udemy. Join us using the Udemy Coupon code on that page to get the course for the best possible price.

Related Posts

27th Mar 2020
Taming G Suite Course

This Complete Administrator’s Guide to Google G Suite walks you through the step by step process of setting up G Suite (Google Apps for Your Domain or Google Apps for Education) as fast as possible. I focus on the best practices and explain why each step and setting is important. I also take you through real-life scenarios you may encounter and show you how to address each one.

Read More >>
26th Mar 2020
Taming REGEX

This course is designed to advance you from beginner to proficient. It is laid out logically so that you can incrementally build your regular expressions knowledge. Essential foundations are established first to facilitate in-depth comprehension of this key skill.

Read More >>
Copyright © 2020 Taming.Tech is a Division of Outsource House [OSH.co.za] | All Rights Reserved | Powered by Doiing.Digital