Snowman
Snowman

Reputation: 32061

Regular expression to match credit card expiration date

I have the following pattern which I'm trying to use to match credit card expiration dates:

(0[1-9]|1[0-2])\/?(([0-9]{4})|[0-9]{2}$)

and I'm testing on the following strings:

02/13
0213
022013
02/2013
02/203
02/2
02/20322

It should only match the first four strings, and the last 3 should not be a match as they are invalid. However the current pattern is also matching the last string. What am I doing wrong?

Upvotes: 20

Views: 43294

Answers (3)

DavidRR
DavidRR

Reputation: 19397

Since we're talking about a credit card expiration date, once you have validated the input date string using one of the fine regex expressions in the other answers, you'll certainly want to confirm that the date is not in the past.

To do so:

  1. Express your input date string as YYYYMM. For example: 201409
  2. Do the same for the current date. For example: 201312
  3. Then simply compare the date strings lexicographically: For example: 201409 ge 201312.

In Perl, ge is the greater than or equal to string comparison operator. Note that as @Dan Cowell advised, credit cards typically expire on the last day of the expiry month, so it would be inappropriate to use the gt (greater than) operator.

Alternatively, if your language doesn't support comparing strings in this fashion, convert both strings to integers and instead do an arithmetic comparison.

Upvotes: 3

forgivenson
forgivenson

Reputation: 4435

Move a right paran:

^(0[1-9]|1[0-2])\/?(([0-9]{4}|[0-9]{2})$)

The end anchor wasn't being applied to the [0-9]{4} option, so more numbers were allowed.

Upvotes: 1

anubhava
anubhava

Reputation: 784908

You're missing start of line anchor ^ and parenthesis are unmatched.

This should work:

re = /^(0[1-9]|1[0-2])\/?([0-9]{4}|[0-9]{2})$/;

OR using word boundaries:

re = /\b(0[1-9]|1[0-2])\/?([0-9]{4}|[0-9]{2})\b/;

Working Demo: http://regex101.com/r/gN5wH2

Upvotes: 47

Related Questions