开发者

Does anyone know of a reg expression for uk date format

开发者 https://www.devze.com 2023-01-16 22:44 出处:网络
Hi does any one know a reg ex for a uk date format e.g. dd/mm/yyyy. The dd or mm can be 1 character e.g. 1/1/2010 but the year must always be 4 characters.

Hi does any one know a reg ex for a uk date format e.g. dd/mm/yyyy.

The dd or mm can be 1 character e.g. 1/1/2010 but the year must always be 4 characters.

Than开发者_如何学运维ks in advance


^\d{1,2}/\d{1,2}/\d{4}$

will match 1/1/2000, 07/05/1999, but also 99/77/8765.

So if you want to do some rudimentary plausibility checking, you need

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

This will still match 31/02/9999, so if you want to catch those, it's getting hairier:

^(?:(?:[12][0-9]|0?[1-9])/0?2|(?:30|[12][0-9]|0?[1-9])/(?:0?[469]|11)|(?:3[01]|[12][0-9]|0?[1-9])/(?:0?[13578]|1[02]))/\d{4}$

But this still won't catch leap years. So, modifying a beast of a regex from regexlib.com:

^(?:(?:(?:(?:31\/(?:0?[13578]|1[02]))|(?:(?:29|30)\/(?:0?[13-9]|1[0-2])))\/(?:1[6-9]|[2-9]\d)\d{2})|(?:29\/0?2\/(?:(?:(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])|(?:1[0-2]))\/(?:(?:1[6-9]|[2-9]\d)\d{2}))$

will match

1/1/2001
31/5/2010
29/02/2000
29/2/2400
23/5/1671
01/1/9000

and fail

31/2/2000
31/6/1800
12/12/90
29/2/2100
33/3/3333

All in all, regular expressions may be able to match dates; validating them is not their forte, but if they are all you can use, it's certainly possible. But looks horrifying :)


Regex is not the right tool for this job.

It is very difficult (but possible) to come up with the regex to match a valid date. Things like ensuring Feb has 29 days on leap year and stuff is not easily doable in regex.

Instead check if your language library provides any function for validating dates.

PHP has one such function called checkdate :

bool checkdate  ( int $month  , int $day  , int $year)


\b(0?[1-9]|[12][0-9]|3[01])[/](0?[1-9]|1[012])[/](19|20)?[0-9]{2}\b

Match :

  • 1/1/2010
  • 01/01/2010

But also invalid dates such as February 31st


^\d{1,2}/\d{1,2}/\d{4}$

In braces there is min and max char count. \d means digit, ^ start, and $ end of string.


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

This wont validate the date, but you can check for format


I ran into the similar requirements. Here is the complete regular expression along with Leap Year validation. Format: dd/MM/yyyy

(3[01]|[12]\d|0[1-9])/(0[13578]|10|12)/((?!0000)\d{4})|(30|[12]\d|0[1-9])/(0[469]|11)/((?!0000)\d{4})|(2[0-8]|[01]\d|0[1-9])/(02)/((?!0000)\d{4})| 29/(02)/(1600|2000|2400|2800|00)|29/(02)/(\d\d)(0[48]|[2468][048]|[13579][26])

It can be easily modified to US format or other EU formats.

edited:

(3[01]|[12]\d|0[1-9])/(0[13578]|10|12)/((?!0000)\d{4})|(30|[12]\d|0[1-9])/(0[469]|11)/((?!0000)\d{4})|(2[0-8]|[01]\d|0[1-9])/(02)/((?!0000)\d{4})|29/(02)/(1600|2000|2400|2800|00)|29/(02)/(\d\d)(0[48]|[2468][048]|[13579][26])


There are two things you want to do, which in my view are best considered separately

1) You want to make sure that the date is a real, actual date. For example the 2019-02-29 isn't a real date whereas 2020-02-29 is a real date because 2020 is a leap year

2) You want to check that the date is in the correct format (so dd/mm/yyyy)

The second point can be done easily enough with a simple RegEx, plenty of examples of that.

To complicate matters, if you ask Firefox if 2019-02-29 is a real date, it'll return NaN, which is what you'd expect.

Chrome, on the other hand will say it is a real date and give you back the 1st of March 2019 - which will validate

Chrome, will also accept a single digit number as a proper date too for some strange reason, feed it "2" and it'll give you full date from 2001 back - which will validate

So first step is to create a function which attempts to decipher a date (no matter the format) and works cross-browser to return a boolean indicating if the date is valid or not

function validatableDate(value) 
{
    Date.prototype.isValid = function() 
    {   // An invalid date object returns NaN for getTime() and NaN is the only
        // object not strictly equal to itself.
        return this.getTime() === this.getTime();
    };
    minTwoDigits = function(n) 
    {   //pads any digit less than 10 with a leading 0
        return (parseInt(n) < 10 ? '0' : '') + parseInt(n);
    }
    var valid_date = false;
    var iso_array = null;
    // check if there are date dividers (gets around chrome allowing single digit numbers)
    if ((value.indexOf('/') != -1) || (value.indexOf('-') != -1)) { //if we're dealing with - dividers we'll do some pre-processing and swap them out for /
        if (value.indexOf('-') != -1) {
            dash_parts = value.split('-');
            value = dash_parts.join("/");
            //if we have a leading year, we'll put it at the end and work things out from there
            if (dash_parts[0].length > 2) {
                value = dash_parts[1] + '/' + dash_parts[2] + '/' + dash_parts[0];
            }
        }

        parts = value.split('/');
        if (parts[0] > 12) { //convert to ISO from UK dd/mm/yyyy format
            iso_array = [parts[2], minTwoDigits(parts[1]), minTwoDigits(parts[0])]
        } else if (parts[1] > 12) { //convert to ISO from American mm/dd/yyyy format                                                
            iso_array = [parts[2], minTwoDigits(parts[0]), minTwoDigits(parts[1])]
        } else //if a date is valid in either UK or US (e.g. 12/12/2017 , 10/10/2017) then we don't particularly care what format it is in - it's valid regardless
        {
            iso_array = [parts[2], minTwoDigits(parts[0]), minTwoDigits(parts[1])]
        }

        if (Array.isArray(iso_array)) {
            value = iso_array.join("-");
            var d = new Date(value + 'T00:00:01Z');
            if (d.isValid()) //test if it is a valid date (there are issues with this in Chrome with Feb)
            {
                valid_date = true;
            }
            //if the month is Feb we need to do another step to cope with Chrome peculiarities
            if (parseInt(iso_array[1]) == 2) {
                month_info = new Date(iso_array[0], iso_array[1], 0);
                //if the day inputed is larger than the last day of the February in that year
                if (iso_array[2] > month_info.getDate()) {
                    valid_date = false;
                }
            }
        }
    }
    return valid_date;
}

That can be compressed down to

function validatableDate(t) {
    Date.prototype.isValid = function () {
        return this.getTime() === this.getTime()
    }, minTwoDigits = function (t) {
        return (parseInt(t) < 10 ? "0" : "") + parseInt(t)
    };
    var a = !1,
        i = null;
    return -1 == t.indexOf("/") && -1 == t.indexOf("-") || (-1 != t.indexOf("-") && (dash_parts = t.split("-"), t = dash_parts.join("/"), dash_parts[0].length > 2 && (t = dash_parts[1] + "/" + dash_parts[2] + "/" + dash_parts[0])), parts = t.split("/"), i = parts[0] > 12 ? [parts[2], minTwoDigits(parts[1]), minTwoDigits(parts[0])] : (parts[1], [parts[2], minTwoDigits(parts[0]), minTwoDigits(parts[1])]), Array.isArray(i) && (t = i.join("-"), new Date(t + "T00:00:01Z").isValid() && (a = !0), 2 == parseInt(i[1]) && (month_info = new Date(i[0], i[1], 0), i[2] > month_info.getDate() && (a = !1)))), a
}

That gets you a cross-browser test as to whether the date can be validated or not and it'll read & decipher dates in formats

  • yyyy-mm-dd
  • dd-mm-yyyy
  • mm-dd-yyyy
  • dd/mm/yyyy
  • mm/dd/yyyy

Once you've validated the date is a real, proper one you can then test the format with a regex. So for UK dd/mm/yy

function dateUK(value) {
    valid_uk_date=false;
    valid_date=validatableDate(value);
    if(valid_date && value.match(/^(0?[1-9]|[12][0-9]|3[01])[\/](0?[1-9]|1[012])[\/]\d{4}$/))
    {   valid_uk_date=true;
    }
    return  valid_uk_date;              
}

You then know that the date is a real one and that it's in the correct format.

For yyyy-mm-dd format, you'd do:

function dateISO(value) {
    valid_iso_date=false;
    valid_date=validatableDate(value);
    if(valid_date && value.match(/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/))
    {   valid_iso_date=true;
    }
    return  valid_iso_date;             
}

It depends how thorough you want to be of course, for a rough check of format sanity a RegEx may be enough for your purposes. If however you want to test if the date is a real one AND if the format is valid then this will hopefully help point you along the way

Thanks

0

精彩评论

暂无评论...
验证码 换一张
取 消