Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

php preg_match a date format "yyyy-MM"

I'm trying to use a modified preg format from preg_match: check birthday format (dd/mm/yyyy) to match credit card expiration dates (yyyy-MM formats)

    if (!preg_match('/([0-9]{4})\-([0-9]{2})/', $expirationDate, $matches)) {
        throw new Services_Payment_Exception('Card expiration date is invalid');
    }

For some reason, it also validate invalid values such as 20111-02 (invalid year). What am I doing wrong here? I want to confirm the year is 4 digits and the month is 2 digits (01, 02.. 12)

like image 660
aporat Avatar asked Mar 28 '12 19:03

aporat


3 Answers

Anchor your regexp:

preg_match('/^([0-9]{4})-([0-9]{2})$/', $expirationDate, $matches)

Your regexp didn't do what you expected because it matches "0111-02" substring of "20111-02".

Anchors ^ and $ match particular positions within the input string: ^ matches the beginning of the string and $ matches the end.

Note also that there is no need to escape the hyphen since it only has a special function in [].

like image 146
Adam Zalcman Avatar answered Sep 28 '22 04:09

Adam Zalcman


Use ^ and $ anchors:

if (!preg_match('/^([0-9]{4})\-([0-9]{2})$/', $expirationDate, $matches)) {
    throw new Services_Payment_Exception('Card expiration date is invalid');
}

to ensure the whole string matches the pattern.

In your example 20111-02 matches because it matches the 0111-02 part of 20111-02.

like image 41
pjumble Avatar answered Sep 28 '22 05:09

pjumble


It's matching 0111-02, which fits your requirements.

Change:

'/([0-9]{4})\-([0-9]{2})/'

to:

'/^([0-9]{4})\-([0-9]{2})$/'

so it only checks against the entirety of the string.

like image 43
ceejayoz Avatar answered Sep 28 '22 05:09

ceejayoz