6

I need a regular expression to validate a timestamp of the format, using Javascript:

YYYY/MM/DD HH:MI:SS

I tried cooking up a few, but seems my regex skills fail to cover something or other.

Please give me a reference or way to do it.

P.S. : I mention regex, only as a suggestion. Im using Javascript and welcome any alternative.

Nietzche-jou
  • 13,657
  • 4
  • 32
  • 45
M.N
  • 10,197
  • 13
  • 44
  • 49
  • 7
    Is 2009/14/35 27:63:60 valid? If not, it's going to be ugly with regexes. – balpha Jun 29 '09 at 11:02
  • What language are you using? If this is Perl, you can invoke code from the regex, which is probably the only way you'll make an easy-to-read check. Just the code to validate if it's a leap year to validate whether Feb 29 exists would make the thing ugly as all get out. – Conspicuous Compiler Jun 29 '09 at 11:05
  • I mention regex, only as a suggestion. Im using Javascript and welcome any alternative. – M.N Jun 29 '09 at 11:07
  • 2
    What's the purpose of the validation? If you truly want to make sure it is valid date, parse it as a date. Regex will simply tell you if it looks like a date, most library functions do this anyway as a first part of a parse! – Ray Hayes Jun 29 '09 at 11:19

13 Answers13

17

I would recommend to use Datejs for this. Parsing the date yourself is not necessary and a Regex is not enough to validate a timestamp. With datejs you could parse the string in a date and you'll get null if its invalid:

Date.parse("2009/06/29 13:30:10", "yyyy/MM/dd HH:mm:ss");
Joey
  • 316,376
  • 76
  • 642
  • 652
Tim Büthe
  • 58,799
  • 16
  • 82
  • 126
9

If you just want to validate the syntax, here is the POSIX regex:

[0-9]{1,4}/[0-9]{1,2}/[0-9]{1,2} [0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}

But if you want to check the semantics, I would process the string using your language of choice, there are too many cases you cannot cover with regular expressions (like leap years/seconds, daylight savings, etc)

soulmerge
  • 68,989
  • 18
  • 113
  • 147
6

You should consider not doing this with regular expressions, but rather just run the string through DateTime with the proper format string. That way you can ensure that it is indeed a valid timestamp and not just something that looks like it.

Joey
  • 316,376
  • 76
  • 642
  • 652
5

Here is a regex I wrote earlier today for validating strings in a format similar to what you mentioned: YYYY-MM-DD hh:mm:ss. It does not identify some bad dates (for example, February 30th) but may be slightly better than using the simplistic \d at each position. Things to note:

  1. you can specify just a date, just a time, or both date + time
  2. time can be in 12-hour or 24-hour format
  3. seconds are optional
  4. am/pm is optional

    const std::string dateAndTimeRegex =
        "^\\s*"                     // ignore whitespace
        "("                         // start of date
            "20[123][0-9]"          // year: 2010, 2011, ..., through 2039
            "\\W"                   // delimiter between year and month; typically will be "-"
            "([0]?[0-9]|1[012])"    // month: 0 through 9, or 00 through 09, or 10 through 12
            "\\W"                   // delimiter between month and day; typically will be "-"
            "([012]?[0-9]|3[01])"   // day: 0 through 9, or 00 through 29, or 30, or 31
        ")?"                        // end of optional date
        "\\s?"                      // optional whitespace
        "("                         // start of time
            "([01]?[0-9]|2[0-3])"   // hour: 0 through 9, or 00 through 19, or 20 through 23
            "\\W"                   // delimiter between hours and minutes; typically will be ":"
            "([0-5][0-9])"          // minute: 00 through 59
            "("                     // start of seconds (optional)
                "\\W"               // delimiter between minutes and seconds; typically will be ":"
                "([0-5][0-9])"      // seconds: 00 through 59
            ")?"                    // end of optional seconds
            "(\\s*[AaPp][Mm])?"     // optional AM, am, PM, pm
        ")?"                        // end of optional time
        "\\s*$";                    // trailing whitespace
    

A comment from @kyrias hints that this regex will fail in a few months once we hit the year 2020. Depending on how you use it, you'll need to change "201[0-9]" to something else.

For example, if you are looking to validate the current date +/- a few years, you could change it to "20[12][0-9]". To validate 2000 through 2099, change it to "20[0-9]{2}".

I've changed the original regex above to look for 2010-2039. Someone else can edit this answer in 20 years if necessary.

Stéphane
  • 17,613
  • 22
  • 82
  • 117
4

I just wrote a Regex to control a MySQL datetime (and I think that it's not so different for Oracle or other database server).

This ReGex is very secure and controls the validity of the date (months in 28, 30 & 31 days, and even years with 29/02). Then, it controls the time. The timestamp format is this one :

YYYY-MM-DD HH:MM:SS

Here is the Regex (quite long) :

((((19|20)([2468][048]|[13579][26]|0[48])|2000)-02-29|((19|20)[0-9]{2}-(0[4678]|1[02])-(0[1-9]|[12][0-9]|30)|(19|20)[0-9]{2}-(0[1359]|11)-(0[1-9]|[12][0-9]|3[01])|(19|20)[0-9]{2}-02-(0[1-9]|1[0-9]|2[0-8])))\s([01][0-9]|2[0-3]):([012345][0-9]):([012345][0-9]))

Matches

2013-04-05 17:59:59 | 2013-07-30 01:22:42 | 2099-12-30 23:59:59 | 2016-02-28 00:00:00

Non-Matches

2016-02-29 -01:01:02 | 3000-04-24 17:42:21 | 2012-03-03 24:24:02 | 2012-03-03 21:60:45

I don't think I can make a more secured one. Very functionnel and tested. Please, if you use it, don't hesitate to give me feedback ;)

FYI : If you just look for the date Regex control without time, please go there to find it : Regular Expression to match valid dates (check my post).

Cheers

Community
  • 1
  • 1
Okipa
  • 482
  • 4
  • 16
2
function validateTimestamp(timestamp) {

    if (!/\d{4}\/\d{2}\/\d{2} \d{2}:\d{2}:\d{2}/.test(timestamp)) {
        return false;
    }

    var split = timestamp.split(/[^\d]+/);

    var year = parseFloat(split[0]);
    var month = parseFloat(split[1]);
    var day = parseFloat(split[2]);

    var hour = parseFloat(split[3]);
    var minute = parseFloat(split[4]);
    var second = parseFloat(split[5]);

    return hour < 25 && minute < 61 && second < 61 && month < 13 && day < 32;

}
James
  • 103,518
  • 28
  • 156
  • 172
2

For a valid date between year 1000 and year 2999 use :

String pattern = "((1\\d{3})|(20\\d{2}))-((0\\d)|(1[0-2]))-(([1-2]\\d)|(3[0-1])) (([0-1]\\d)|(2[0-3])):([0-5]\\d):([0-5]\\d)";

The months can vary between 01 and 12, the days between 01 and 31 and the time between 00:00:00 and 23:59:59.

riroo
  • 144
  • 2
  • 15
2

Here is how I build up a regex matching exactly SQL Timestamp yyyy-mm-dd hh:mm:ss in the range [1970-01-01 00:00:00, 2037-12-31 23:59:59]

$leapYear = "(19[79][26]|198[048]|20[02][048]|20[13][26])";
$leapDate = "$leapYear-02-29";

$regularYear = "(19[789][0-9]|20[012][0-9]|203[0-7])";
$regularFebruaryDate = "02-([01][1-9]|2[0-8])";
$month31Date = "(0[13578]|10|12)-([012][1-9]|3[01])";
$month30Date = "(0[469]|11)-([012][1-9]|30)";
$regularDate = "$regularYear-($regularFebruaryDate|$month30Date|$month31Date)";

$hours = "(2[0-3]|[01][0-9])";
$minutes = "[0-5][0-9]";
$seconds = "[0-5][0-9]";

$sqlTimestamp = "($leapDate|$regularDate) $hours:$minutes:$seconds";

Note: I avoided the year 2038 to have one less edge-case. The max possible SQL timestamp is 2038-01-19 03:14:07.

Jonasjso
  • 191
  • 1
  • 3
1

perl style: [12]\d{3}/[01]\d/[0-3]\d [0-2]\d(?::[0-5]\d){2}

Nikolai Ruhe
  • 79,600
  • 16
  • 173
  • 195
1

Using

(\d\d)?\d\d\/\d\d?/\d\d? \d\d?:\d\d:\d\d

could validate the syntax, but as balpha points out, that doesn't make it a valid date.

Gene Gotimer
  • 6,781
  • 2
  • 27
  • 44
1
function isTimestamp($input){
            var $regex = /^\d\d\d\d-(0?[1-9]|1[0-2])-(0?[1-9]|[12][0-9]|3[01]) (00|[0-9]|1[0-9]|2[0-3]):([0-9]|[0-5][0-9]):([0-9]|[0-5][0-9])$/;
            return $regex.test($input);
        }

check please

AndroCoder
  • 194
  • 1
  • 14
1

This is the regex you are looking for:

[0-9]{4}/(0[1-9]|1[0-2])/(0[1-9]|[1-2][0-9]|3[0-1]) (2[0-3]|[01][0-9]):[0-5][0-9]:[0-5][0-9]
Mehmet nuri
  • 460
  • 4
  • 5
0

Regular-Expressions.info is a nice source of information about RegEx, it also has a good tutorial.

RuudKok
  • 5,217
  • 2
  • 23
  • 26
  • 1
    A comment why this is downvoted would be deeply appreciated. I cannot see why giving a link to a RegEx reference website should be downvoted, especially when it states in the question "Please give me a reference or way to do it." – RuudKok Jun 29 '09 at 11:24