Simple Date Validation

« Return to Article
  • poeorlco 2012-04-19 13:34
    -insert jwz regexp quote here-
  • Annon 2012-04-19 13:37
    frist (this is not spam)
  • KattMan 2012-04-19 13:38
    So what is wrong with trying a DateTime.TryParse and letting it either set a proper date for you or return false if it isn't valid? I actually think there is a problem with some people using regex for everything when it isn't needed. It's a tool with certian uses, it is not a swiss army knife for everything.
    Why re-invent the wheel?
  • snoofle 2012-04-19 13:40
    Alex:
    new Regex(@"^((0?[1-9]|[12][1-9]|3[01])\.(0?[13578]|1[02])\.20[0-9]{2}|(0?[1-9]|[12][1-9]|30)\.(0?[13456789]|1[012])\.20[0-9]{2}|(0?[1-9]|1[1-9]|2[0-8])\.(0?[123456789]|1[012])\.20[0-9]{2}|(0?[1-9]|[12][1-9])\.(0?[123456789]|1[012])\.20(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96))$")


    That seems reasonable. As we've often pointed out, doing date validation is hard, so it makes sense that anyone doing date validation would use a hard RE!
  • MSNetExpert 2012-04-19 13:43
    The reality of it is, DateTime.TryParse uses the exact same Regex internally ... This smart Joe has actually optimized the code by removing one useless function call to TryParse
  • snoofle 2012-04-19 13:44
    KattMan:
    So what is wrong with trying a DateTime.TryParse and letting it either set a proper date for you or return false if it isn't valid? I actually think there is a problem with some people using regex for everything when it isn't needed. It's a tool with certian uses, it is not a swiss army knife for everything.
    Why re-invent the wheel?
    I can't speak for other languages, but in java, you can do: new SimpleDateFormat("yyyyMMdd").parse("20121143") and get Dec 13, 2012, which doesn't exactly let you know that the input was in/valid.
  • KattMan 2012-04-19 13:47
    MSNetExpert:
    The reality of it is, DateTime.TryParse uses the exact same Regex internally ... This smart Joe has actually optimized the code by removing one useless function call to TryParse


    Maybe, how do you know he didn't add a bug with a transposition of two characters, or missing a key stroke, or changing a charater somewhere in there? If he did any of these, debugging it would be a pain.
  • KattMan 2012-04-19 13:48
    snoofle:
    KattMan:
    So what is wrong with trying a DateTime.TryParse and letting it either set a proper date for you or return false if it isn't valid? I actually think there is a problem with some people using regex for everything when it isn't needed. It's a tool with certian uses, it is not a swiss army knife for everything.
    Why re-invent the wheel?
    I can't speak for other languages, but in java, you can do: new SimpleDateFormat("yyyyMMdd").parse("20121143") and get Dec 13, 2012, which doesn't exactly let you know that the input was in/valid.

    This is true, but proper usage of input controls can help with this. If it is a flat file read, might need to take a different route, I'll admit that.
  • Nick V 2012-04-19 14:07
    I do not see what the issue is, here. If you are doing client-side validation, which is always a good idea, using a regex to validate your date (by the way: this is a good regex to validate a date) is not a bad idea at all.

    Of course, in 2012: JQuery, Telerik, etc...

    I apologize but WTF this ain't.
  • da Doctah 2012-04-19 14:18
    I heard from someone at Apple that Siri is actually just one great big regex.
  • Rajendra Kumar 2012-04-19 14:23
    Dearest Pros,
    I am needing of program just like this. Only it should be having ANSI C99 codes. I am team leader at major South Asian company and it is important this be delivered to my direct reports. That way I can get back to drinking chai and smoking fags. Plz send to Rajkum@gmail.biz, it's URGENT!
  • ThingGuy McGuyThing 2012-04-19 14:23
    I really get the impression that this bit is supposed to detect leap-years:

    20(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)


    ...but I can't for the life of me find a corresponding 02/29 type of sequence.
  • Nagesh 2012-04-19 14:26
    This is clear work of politics in project.
    This person is trying to get project bonus for maximum length of stay in project. So writing of unmentionable code is one way of making this achieving goal.

    I salute this person's wise-dome.
  • frits 2012-04-19 14:28
    da Doctah:
    I heard from someone at Apple that Siri is actually just one great big regex.

    Actually, I heard she's Thetan Level VI already (same thing really).
  • Ani Moose 2012-04-19 14:33
    KattMan:
    MSNetExpert:
    The reality of it is, DateTime.TryParse uses the exact same Regex internally ... This smart Joe has actually optimized the code by removing one useless function call to TryParse


    Maybe, how do you know he didn't add a bug with a transposition of two characters, or missing a key stroke, or changing a charater somewhere in there? If he did any of these, debugging it would be a pain.


    Oh... like the missing 10th and 20th days of the month?
    Regex(@"^((0?[1-9]|[12][1-9]|3[01])
  • Ani Moose 2012-04-19 14:37
    ThingGuy McGuyThing:
    I really get the impression that this bit is supposed to detect leap-years:

    20(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)


    ...but I can't for the life of me find a corresponding 02/29 type of sequence.


    It's here:
    (0?[1-9]|[12][1-9])\.(0?[123456789]|1[012])\.20(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)

    You just can't have a Feb 10th or Feb 20th.
  • Maltz 2012-04-19 14:41
    ThingGuy McGuyThing:
    I really get the impression that this bit is supposed to detect leap-years:

    20(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)


    ...but I can't for the life of me find a corresponding 02/29 type of sequence.


    Beyond that, it's still wrong. 1900 wasn't a leap year.

    Leap years are every 4 years... except every 100... except every 400. So 1700, 1800, 1900 are not leap years, 1600, 2000, and 2400 are.
  • Dude 2012-04-19 14:43
    It gets a bit more weird than that, due to redundancy caused by how February is checked, you can have a 20th of any month, and a 10th of any month in year % 4 == 0 (note that this is not correct for detecting leap years you also need year % 400 != 0)
  • Dude 2012-04-19 14:44
    And reading the comment above mine, I see that I was wrong about the century rule as well. Just more reason why you should let the date library handle it.
  • Rick 2012-04-19 14:47
    snoofle:
    KattMan:
    So what is wrong with trying a DateTime.TryParse and letting it either set a proper date for you or return false if it isn't valid? I actually think there is a problem with some people using regex for everything when it isn't needed. It's a tool with certian uses, it is not a swiss army knife for everything.
    Why re-invent the wheel?
    I can't speak for other languages, but in java, you can do: new SimpleDateFormat("yyyyMMdd").parse("20121143") and get Dec 13, 2012, which doesn't exactly let you know that the input was in/valid.
    Granted the default is wrong, but applying setLenient(false) to a SimpleDateFormat object is not all that hard.
  • HP PhaserJet 2012-04-19 14:55
    da Doctah:
    I heard from someone at Apple that Siri is actually just one great big regex.
    The offspring of Com Truise and Hatie Kolem's is's a giant dinosuar with tiny arms (what a cruel twist of fate) and what a twisted cruel fatty are you!
  • KattMan 2012-04-19 15:02
    Ok, here's how I would probably handle it just to cover my own butt.

    Let regex do what it does best, validate the PATTERN matches one of the following: "99/99/9999", "99-99-9999", "9999/99/99" or "9999-99-99", this is easy and accounts for day, month or year first. This lets me know it is the form I require, then use date functions to validate that it is a proper date according to current localization. No more missing days and bad leap years and the regex makes sure the pattern is correct.
  • greyfade 2012-04-19 15:12
    I made a better one:

    /^(((0?[13578]|1[02])\/([0-2]?[1-9]|[123]0|31)|(0?[469]|11)\/([0-2]?[1-9]|[123]0)|0?2\/([0-1]?[1-9]|[12]0|2[1-8]))\/(19|20)?[0-9]{2}|0?2\/29\/((20)?00|(19|20)?([02468][48]|[13579][26]|[2468]0)))$/


    It's not only a lot shorter, but it's easier to read, and correctly matches all dates from 1/1/1900 to 12/31/2099, with no false positive. :)
  • Yoh 2012-04-19 15:27
    Sorry but your "easier to read" regex is still a pain in the ass to read.

    And what happens when the requirements for the input changes? I mean, there are a ton of different ways to specify a date.

    This is really not a very scalable solution, and therefore not an appropriate tool in my opinion.
  • Zylon 2012-04-19 15:28
    Annon:
    frist (this is not spam)

    Wrong on both counts.
  • Sam I am 2012-04-19 15:31
    "(1[0-2]|0?[1-9])/(3[0-1]|[1-2][0-9]|0?[1-9])/[0-9][0-9][0-9][0-9]"
  • LANMind 2012-04-19 15:39
    KattMan:
    MSNetExpert:
    The reality of it is, DateTime.TryParse uses the exact same Regex internally ... This smart Joe has actually optimized the code by removing one useless function call to TryParse


    Maybe, how do you know he didn't add a bug with a transposition of two characters, or missing a key stroke, or changing a charater somewhere in there? If he did any of these, debugging it would be a pain.


    You have difficulty recognizing sarcasm, don't you?
  • The Mr. T Experience 2012-04-19 15:46
    Zylon:
    Annon:
    frist (this is not spam)

    Wrong on both counts.
    Wow. Your so inciteful.
  • Jay 2012-04-19 15:53
    This demonstrates both the power of RegExes -- a fairly complex validation done in just 3 or 4 lines of code -- and their danger -- it's very difficult to comprehend, so the error about the 10th and 20th of the month being illegal slipped through.

    I suppose in this case maintainability isn't a big issue. It's unlikely that the numbers of days in a month will change any time soon.

    Though curiously, this validation only accepts dates in the 21st century. That's fine if the dates are all going to be in the recent past or near future, like order date and shipping date of new orders. But it will reject the birth date of anyone over 12 years old, not to mention any dates on other records that go back that far.
  • greyfade 2012-04-19 16:11
    My regex is used in a system whose data formats are specified by a handful of US government standards. Those standards rarely, if ever, change such minutiae. Neither I nor any of my coworkers were concerned about needing to change it.

    It was both the appropriate tool in my case, and the only feasible option at the time.
  • Yoshord 2012-04-19 16:19
    Maltz:
    ThingGuy McGuyThing:
    I really get the impression that this bit is supposed to detect leap-years:

    20(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)

    ...but I can't for the life of me find a corresponding 02/29 type of sequence.


    Beyond that, it's still wrong. 1900 wasn't a leap year.

    Leap years are every 4 years... except every 100... except every 400. So 1700, 1800, 1900 are not leap years, 1600, 2000, and 2400 are.


    This regex doesn't think 1900 is a leap year; it doesn't match 2100 or 1800 either, so I don't know why you felt the need to bring up the fact that those aren't leap years.
  • big picture thinker 2012-04-19 16:28
    Don't know why the entire validation is regex. You could use it for parts, but I think it would be better to split the year, month, and date parts and then perform some procedural logic on those parts.
  • taixzo 2012-04-19 16:41
    Yoshord:
    Maltz:
    ThingGuy McGuyThing:
    I really get the impression that this bit is supposed to detect leap-years:

    20(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)

    ...but I can't for the life of me find a corresponding 02/29 type of sequence.


    Beyond that, it's still wrong. 1900 wasn't a leap year.

    Leap years are every 4 years... except every 100... except every 400. So 1700, 1800, 1900 are not leap years, 1600, 2000, and 2400 are.


    This regex doesn't think 1900 is a leap year; it doesn't match 2100 or 1800 either, so I don't know why you felt the need to bring up the fact that those aren't leap years.


    The regex doesn't think 1900 is anything. Look at the start of that sequence: it starts with 20. So it will only accept years from 2000 to 2099, inclusive.
  • qbolec 2012-04-19 16:49
    I think we need a library, that allows us to describe regular languages using productions, and at compile time compiles it to regexp (or even to automata).

    I mean something like:

    const DateRegExp = RegExp{
    UsualDay >= [1-9]|1\d|2[0-8],
    Month >= [1-9]|1[0-2],
    Year >= \d+,
    LongDay >= 29|30,
    LongMonth >= [13-9]|1[0-2],
    LongerDay >= 31,
    LongerMonth >= [13578]|1[02],
    OtherYearDate >= LongerDay.LongerMonth.Year | LongDay.LongMonth.Year,
    OtherYearDate >= UsualDay.Month.Year,
    DivisibleBy4 >= (\d*([02468][048]|[13579][26])) and not 0.+,
    DivisibleBy100 >= \d*00 and not 0.+,
    DivislbleBy400 >= (DivisbleBy4)00 and not 0.+,
    LeapYear >= DivisibleBy400 or (DivisibleBy4 and not DivisibleBy100),
    LeapYearBonus >= 29.02.LeapYear,
    Date >= LeapYearBonus | OtherYearDate,
    };


    You may notice that my notation of gramar resembles context free grammar, but is actually regular, as I only use non-terminals defined previously. I also want to use negation and intersection, which still keeps me inside regular languages.

    Do you know a language+compiler that supports somthing like that?
  • Neil 2012-04-19 17:13
    I was almost incited to reply to The Mr. T Experience.
  • Not sure if Fry or just Philip 2012-04-19 17:36
    qbolec:
    I think we need a library, that allows us to describe regular languages using productions, and at compile time compiles it to regexp (or even to automata).

    I mean something like:

    const DateRegExp = RegExp{
    UsualDay >= [1-9]|1\d|2[0-8],
    Month >= [1-9]|1[0-2],
    Year >= \d+,
    LongDay >= 29|30,
    LongMonth >= [13-9]|1[0-2],
    LongerDay >= 31,
    LongerMonth >= [13578]|1[02],
    OtherYearDate >= LongerDay.LongerMonth.Year | LongDay.LongMonth.Year,
    OtherYearDate >= UsualDay.Month.Year,
    DivisibleBy4 >= (\d*([02468][048]|[13579][26])) and not 0.+,
    DivisibleBy100 >= \d*00 and not 0.+,
    DivislbleBy400 >= (DivisbleBy4)00 and not 0.+,
    LeapYear >= DivisibleBy400 or (DivisibleBy4 and not DivisibleBy100),
    LeapYearBonus >= 29.02.LeapYear,
    Date >= LeapYearBonus | OtherYearDate,
    };


    You may notice that my notation of gramar resembles context free grammar, but is actually regular, as I only use non-terminals defined previously. I also want to use negation and intersection, which still keeps me inside regular languages.

    Do you know a language+compiler that supports somthing like that?

    Yup. All of them. Instead of a snappy one-liner, split the regex into several commented parts. Pros: you don't have to learn a whole new language, you use regex. Cons: you still have to use regex.
  • Jerry 2012-04-19 17:41
    MSNetExpert:
    The reality of it is, DateTime.TryParse uses the exact same Regex internally ... This smart Joe has actually optimized the code by removing one useless function call to TryParse
    What's more, libraries can change out from under you, introducing hard-to-debug new behaviors in your app.

    Far better to write your own stable code. Then you know it will work, now and forever.
  • Timm 2012-04-19 17:42
    qbolec:
    Do you know a language+compiler that supports somthing like that?
    I don't use it myself, but from what I hear, emacs can do anything.
  • sdhfs 2012-04-19 17:49
    Maltz:
    ThingGuy McGuyThing:
    I really get the impression that this bit is supposed to detect leap-years:

    20(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)


    ...but I can't for the life of me find a corresponding 02/29 type of sequence.


    Beyond that, it's still wrong. 1900 wasn't a leap year.

    Leap years are every 4 years... except every 100... except every 400. So 1700, 1800, 1900 are not leap years, 1600, 2000, and 2400 are.
    Too lazy to have a look at how many people have already said this....

    how is 1900 in there?
  • Titor 2012-04-19 17:53
    taixzo:
    Yoshord:
    Maltz:
    ThingGuy McGuyThing:
    I really get the impression that this bit is supposed to detect leap-years:

    20(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)

    ...but I can't for the life of me find a corresponding 02/29 type of sequence.


    Beyond that, it's still wrong. 1900 wasn't a leap year.

    Leap years are every 4 years... except every 100... except every 400. So 1700, 1800, 1900 are not leap years, 1600, 2000, and 2400 are.


    This regex doesn't think 1900 is a leap year; it doesn't match 2100 or 1800 either, so I don't know why you felt the need to bring up the fact that those aren't leap years.


    The regex doesn't think 1900 is anything. Look at the start of that sequence: it starts with 20. So it will only accept years from 2000 to 2099, inclusive.
    We didn't have Leap years in the 20th Century, and you might be interested to hear they get rid of them before the 22nd....
  • RandomGuy 2012-04-19 18:03
    Ani Moose:
    ThingGuy McGuyThing:
    I really get the impression that this bit is supposed to detect leap-years:

    20(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)


    ...but I can't for the life of me find a corresponding 02/29 type of sequence.


    It's here:
    (0?[1-9]|[12][1-9])\.(0?[123456789]|1[012])\.20(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)

    You just can't have a Feb 10th or Feb 20th.

    That's here:
    (0?[1-9]|1[1-9]|2[0-8])\.(0?[123456789]|1[012])\.20[0-9]{2}

    Actually, the Feb 29th part could have been reduced to
    (29)\.(0?2)\.20([02468][048]|[13579][26])

    I'd rather criticize the very limited time period this code is valid -- but who knows, if earth still exists in 2100 ...
  • Oblig 2012-04-19 18:23
    You have a problem.

    You decide to use a regex.

    Now you have 00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96 problems.
  • barf4eva 2012-04-19 18:44
    Jerry:
    MSNetExpert:
    The reality of it is, DateTime.TryParse uses the exact same Regex internally ... This smart Joe has actually optimized the code by removing one useless function call to TryParse
    What's more, libraries can change out from under you, introducing hard-to-debug new behaviors in your app.

    Far better to write your own stable code. Then you know it will work, now and forever.


    OK, now I'm not sure if you guys are still being sarcastic or not.

    And it is scaring me!
  • Dave 2012-04-19 19:08
    TRWTF is having a national date format that puts Months first.

    Day Month Year has a logic to it, but is ordered the wrong way round for sorting.

    Year Month Day makes complete sense, and is sortable, (so long as the year is 4 digits - don't forget Y2K compliance!)

    But Month Day Year has neither logic nor sortability.
  • Sutherlands 2012-04-19 20:02
    GAH! This is SO horrible! Doesn't he know that you should store the regex for repeat use, since the most expensive part is creating it? *sigh*
  • LOADING 2012-04-19 20:33
    KattMan:
    So what is wrong with trying a DateTime.TryParse and letting it either set a proper date for you or return false if it isn't valid? I actually think there is a problem with some people using regex for everything when it isn't needed. It's a tool with certian uses, it is not a swiss army knife for everything.
    Why re-invent the wheel?


    "Reinventing the wheel" is inappropriate here. This is a phrase easier said than justified. A full datetime implementation is a series of wheels, if you want to compare it to a clock or the orbital characteristics of the planet Earth.

    The wheel is simple and works, accurate date validation and handling is a complex process. You can get away with reinventing the wheel. You can do so with out doing anything too complex. You can make a derivative for another purpose or type of terrain, indeed, the mechanical and industrial ages were brought about by a few simple reinventions of the wheel and the subsequent application of the inventions.

    I can forgive someone for remaking there own version of something simple, or an alternative version. But when it comes to more complex things that are already done for you, you can't get away with it, use a library that is reasonably accurate and has been heavily debugged.
  • Tom 2012-04-19 20:49
    ThingGuy McGuyThing:
    I really get the impression that this bit is supposed to detect leap-years:

    20(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)


    ...but I can't for the life of me find a corresponding 02/29 type of sequence.



    TRWTF is that you looked that closely.
  • The Mr. T Experience 2012-04-19 22:54
    Neil:
    I was almost incited to reply to The Mr. T Experience.

    ;D
  • Kuba 2012-04-19 23:01
    KattMan:
    MSNetExpert:
    The reality of it is, DateTime.TryParse uses the exact same Regex internally ... This smart Joe has actually optimized the code by removing one useless function call to TryParse


    Maybe, how do you know he didn't add a bug with a transposition of two characters, or missing a key stroke, or changing a charater somewhere in there? If he did any of these, debugging it would be a pain.
    Obviously, you have a test harness for that regex, right? RIGHT?
  • default_ex 2012-04-19 23:08
    That's some ugly regex for validating a date, even considering it invalidates (some) leap years. But then I've recently written several hundred lines of regex to parse a C-like language (without trimming comments), probably don't deserve the right to call a single line of regex ugly.
  • Kuba 2012-04-19 23:22
    qbolec:
    I think we need a library, that allows us to describe regular languages using productions, and at compile time compiles it to regexp (or even to automata).

    I mean something like:

    const DateRegExp = RegExp{
    UsualDay >= [1-9]|1\d|2[0-8],
    Month >= [1-9]|1[0-2],
    Year >= \d+,
    LongDay >= 29|30,
    \[...\]

    Date >= LeapYearBonus | OtherYearDate,
    };
    You may notice that my notation of gramar resembles context free grammar, but is actually regular, as I only use non-terminals defined previously. I also want to use negation and intersection, which still keeps me inside regular languages.

    Do you know a language+compiler that supports somthing like that?
    LISP of course supports it because it supports arbitrary compile-time computation. C++ also supports it, the expression template pattern is your friend, there are even libraries that implement it all for you -- say Boost Spirit.
  • lolwtf 2012-04-19 23:39
    Are you sure that's a regex? It might just be thinly disguised exploit shellcode.
  • Matt Westwood 2012-04-20 01:10
    Dude:
    And reading the comment above mine, I see that I was wrong about the century rule as well. Just more reason why you should let the date library handle it.

    The real WTF is that there are software professionals who don't understand a piece of such basic general knowledge about how the standard fucking calendar is constructed.

    One of the first exercises given to prospective candidates for a job in my company is to write a short program for counting the number of days between two dates reported in the Gregorian calendar. Checking for accurate handling of leap years is one of the crucial factors. If you're as clueless about the world around you as not to understand that, you're too clueless to work for me.
  • L. 2012-04-20 01:56
    Nick V:
    I do not see what the issue is, here. If you are doing client-side validation, which is always a good idea, using a regex to validate your date (by the way: this is a good regex to validate a date) is not a bad idea at all.

    Of course, in 2012: JQuery, Telerik, etc...

    I apologize but WTF this ain't.


    Erm... this is a regex to validate a date ... but good lmfao . who the hell hardcodes years and forgets about post 2100... if you're going to hardcode it, do it till the end.
  • L. 2012-04-20 02:05
    Ani Moose:
    ThingGuy McGuyThing:
    I really get the impression that this bit is supposed to detect leap-years:

    20(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)


    ...but I can't for the life of me find a corresponding 02/29 type of sequence.


    It's here:
    (0?[1-9]|[12][1-9])\.(0?[123456789]|1[012])\.20(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)

    You just can't have a Feb 10th or Feb 20th.


    Quick question though, why not use d at all ?
  • L. 2012-04-20 02:08
    Matt Westwood:
    Dude:
    And reading the comment above mine, I see that I was wrong about the century rule as well. Just more reason why you should let the date library handle it.

    The real WTF is that there are software professionals who don't understand a piece of such basic general knowledge about how the standard fucking calendar is constructed.

    One of the first exercises given to prospective candidates for a job in my company is to write a short program for counting the number of days between two dates reported in the Gregorian calendar. Checking for accurate handling of leap years is one of the crucial factors. If you're as clueless about the world around you as not to understand that, you're too clueless to work for me.


    Shh Westwood, we all know you're unemployed anyway - and a sock puppet of Zunesis, and we all know what zunie does to socks...
  • Nappy 2012-04-20 03:34
    Dave:
    TRWTF is having a national date format that puts Months first.

    Day Month Year has a logic to it, but is ordered the wrong way round for sorting.

    Year Month Day makes complete sense, and is sortable, (so long as the year is 4 digits - don't forget Y2K compliance!)

    But Month Day Year has neither logic nor sortability.


    The logic is in the way it is said.
    But if you have an international audience it's best to make it explicit i usually add (DD/MM/YYYY) and a picker so everybody knows for filename yyyymmdd makes the best sorting sense.
    And an other pain is the / . - used to separate the parts (and probably 16 other chars used)
  • codemonkey73 2012-04-20 04:12
    snoofle:
    KattMan:
    So what is wrong with trying a DateTime.TryParse and letting it either set a proper date for you or return false if it isn't valid? I actually think there is a problem with some people using regex for everything when it isn't needed. It's a tool with certian uses, it is not a swiss army knife for everything.
    Why re-invent the wheel?
    I can't speak for other languages, but in java, you can do: new SimpleDateFormat("yyyyMMdd").parse("20121143") and get Dec 13, 2012, which doesn't exactly let you know that the input was in/valid.


    Then the real WTF is java, this behaviour is completly brain dead so much so it is what javascript does as well.
  • dkf 2012-04-20 04:19
    lolwtf:
    Are you sure that's a regex? It might just be thinly disguised exploit shellcode.
    Given the bulk of that thing, the one thing it isn't is thinly disguised. Can shellcode be “thickly disguised”?

    (Overall, all this WTF shows is that jwz was right when the regexp user doesn't know what they're doing. Depressing…)
  • tchize 2012-04-20 04:29
    snoofle:
    I can't speak for other languages, but in java, you can do: new SimpleDateFormat("yyyyMMdd").parse("20121143") and get Dec 13, 2012, which doesn't exactly let you know that the input was in/valid.

    I can't speak for you, but when i use an objet in java or other languages, i make sure to read an understand the documentation before claiming it won't work the way i want.
    By default, parsing is lenient: If the input is not in the form used by this object's format method but can still be parsed as a date, then the parse succeeds. Clients may insist on strict adherence to the format by calling setLenient(false)
  • Dave 2012-04-20 05:23
    KattMan:
    So what is wrong with trying a DateTime.TryParse and letting it either set a proper date for you or return false if it isn't valid? I actually think there is a problem with some people using regex for everything when it isn't needed. It's a tool with certian uses, it is not a swiss army knife for everything.
    Why re-invent the wheel?


    Sigh. You're new around here, aren't you?
  • Dave 2012-04-20 05:25
    Nappy:
    Dave:

    But Month Day Year has neither logic nor sortability.

    The logic is in the way it is said.

    "The fourth of July, 1776"?
  • daef 2012-04-20 06:02
    Submitter here :-)

    The reason that 20's were rejected was the reason I fell over that piece of shiny regex.

    There were about 5 other Versions of the same regex all over the Project - different Versions had different bugs (couldn't even find one that passed a simple Test I wrote just for fun)

    It was simply replaced by a DateTime.TryParse btw.

    And WTF-Joe isn't a coworker anymore - so it didn't help him to stay.
  • bb 2012-04-20 08:22
    If so; The Y3k bug is here!
  • ¯\(°_o)/¯ I DUNNO LOL 2012-04-20 09:39
    daef:
    There were about 5 other Versions of the same regex all over the Project - different Versions had different bugs (couldn't even find one that passed a simple Test I wrote just for fun)

    Ah, so I see that Joe was an adherent to the WET principle, too!

    It would have also caused problems if you wanted to localize to US M0/DD/YYYY format or ISO YYYY-MM-DD format.
  • F 2012-04-20 09:39
    Maltz:
    ThingGuy McGuyThing:
    I really get the impression that this bit is supposed to detect leap-years:

    20(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96)


    ...but I can't for the life of me find a corresponding 02/29 type of sequence.


    Beyond that, it's still wrong. 1900 wasn't a leap year.

    Leap years are every 4 years... except every 100... except every 400. So 1700, 1800, 1900 are not leap years, 1600, 2000, and 2400 are.


    However, as it only allows years in the range 2000-2099 in the first place, the fact that 1900 and 2100 aren't leap years is about as relevant as the fact that there was no year zero.
  • Shut up foo' 2012-04-20 09:46
    The Mr. T Experience:
    Zylon:
    Annon:
    frist (this is not spam)

    Wrong on both counts.
    Wow. Your so inciteful.


    It's "You're" and "insightful". Maybe you need a regex spell-checker.
  • Peter 2012-04-20 10:24
    KattMan:
    Let regex do what it does best, validate the PATTERN matches one of the following: "99/99/9999", "99-99-9999", "9999/99/99" or "9999-99-99", this is easy and accounts for day, month or year first.
    Does this mean that you think 1/1/2012 (say) should be rejected as invalid?
  • airdrik 2012-04-20 10:41
    big picture thinker:
    Don't know why the entire validation is regex. You could use it for parts, but I think it would be better to split the year, month, and date parts and then perform some procedural logic on those parts.

    Absolutely, and who could argue with code that looks like this:

    def valiDate(dateStr):
    """Checks that the given date string matches the date format dd.mm.yyyy (leading zeros optional, only accepts dates in the 21st century, but includes leap year validations for all dates between 2000 and 2099, including 2000! (which makes it tehcoolzor!))
    (I used to have this in a one-line regex by my manager said that it was too long and convoluted and that I should swap it out for procedural code, so I decided to write this in python because python has some nice string manipulashuns built-in and I can write it in fewr linez than if it we're c#)"""
    if dateStr.count('.') != 2:
    return False
    day, month, year = dateStr.split('.')
    if (len(day) == 2 and day[0] == '0' or len(day) == 1) and day[-1] in '123456789' or day[0] in '12' and day[1] in '123456789' or day[0] == '3' and day[1] in '01':
    if (len(month) == 2 and month[0] == '0' or len(month) == 1) and month[-1] in '13578' or month[0] == '1' and month[1] in '02':
    if len(year) == 4 and year[:2] == '20' and all(y in '1234567890' for y in year[2:]):
    return True
    if (len(day) == 2 and day[0] == '0' or len(day) == 1) and day[-1] in '123456789' or day[0] in '12' and day[1] in '123456789' or day == '30':
    if (len(month) == 2 and month[0] == '0' or len(month) == 1) and month[-1] in '13456789' or month[0] == '1' and month[1] in '012':
    if len(year) == 4 and year[:2] == '20' and all(y in '1234567890' for y in year[2:]):
    return True
    if (len(day) == 2 and day[0] == '0' or len(day) == 1) and day[-1] in '123456789' or day[0] == '1' and day[1] in '123456789' or day[0] == '2' and day[1] in '012345678':
    if (len(month) == 2 and month[0] == '0' or len(month) == 1) and month[-1] in '123456789' or month[0] == '1' and month[1] in '012':
    if len(year) == 4 and year[:2] == '20' and all(y in '1234567890' for y in year[2:]):
    return True
    if (len(day) == 2 and day[0] == '0' or len(day) == 1) and day[-1] in '123456789' or day[0] in '12' and day[1] in '123456789':
    if (len(month) == 2 and month[0] == '0' or len(month) == 1) and month[-1] in '123456789' or month[0] == '1' and month[1] in '012':
    if len(year) == 4 and year[:2] == '20' and year[2:] in ('00', '04', '08', '12', '16', '20', '24', '28', '32', '36', '40', '44', '48', '52', '56', '60', '64', '68', '72', '76', '80', '84', '88', '92', '96'):
    return True
    return False


    Procedural code is so much better than Regexes
  • Re: Simple Date Validation 2012-04-20 12:25
    Typical WTF idiocy responses (at least those that weren't trolls). Validating a date is a two step operation. First, parse the string into numbers for month, day, and year. Second, ensure that the month, day, and year are a valid date. Trying to cram a two part operation into a single line is a guaranteed source of WTFs, typically done by programmers who got A's on all of their homework problems but are complete disaster's when it comes to real work on production systems.
  • asdf 2012-04-20 13:02
    qbolec:
    I think we need a library, that allows us to describe regular languages using productions, and at compile time compiles it to regexp (or even to automata).

    I mean something like:

    const DateRegExp = RegExp{
    UsualDay >= [1-9]|1\d|2[0-8],
    Month >= [1-9]|1[0-2],
    Year >= \d+,
    LongDay >= 29|30,
    LongMonth >= [13-9]|1[0-2],
    LongerDay >= 31,
    LongerMonth >= [13578]|1[02],
    OtherYearDate >= LongerDay.LongerMonth.Year | LongDay.LongMonth.Year,
    OtherYearDate >= UsualDay.Month.Year,
    DivisibleBy4 >= (\d*([02468][048]|[13579][26])) and not 0.+,
    DivisibleBy100 >= \d*00 and not 0.+,
    DivislbleBy400 >= (DivisbleBy4)00 and not 0.+,
    LeapYear >= DivisibleBy400 or (DivisibleBy4 and not DivisibleBy100),
    LeapYearBonus >= 29.02.LeapYear,
    Date >= LeapYearBonus | OtherYearDate,
    };


    You may notice that my notation of gramar resembles context free grammar, but is actually regular, as I only use non-terminals defined previously. I also want to use negation and intersection, which still keeps me inside regular languages.

    Do you know a language+compiler that supports somthing like that?


    https://metacpan.org/module/Regexp::Grammars
  • Darkstar 2012-04-20 13:58
    Using regular expressions to validate dates just isn't the right tool for the job. It is painstakinly complicated to make sure that all cases are covered.

    A quick brute force check of this code revealed that the 10th of every month isn't accepted as a valid date. Did you see that?

    This is just an example of why regular expressions shouldn't be used - they are great for validating syntax, but suck at validating semantics.

    Also, my check above doesn't cover all the *invalid* dates that this regex may accept as valid.

    The only sane approach is to extract day, month and year, and then do checks on them. It is more readable and doesn't open up for crazy flukes like then one above.
  • Darkstar 2012-04-20 13:59
    ...and Perl 6, of course.
  • Nagesh 2012-04-20 14:00
    Regex is only used to show off knowhow. In real life program I am yet to find any good use for it.
  • x 2012-04-20 14:07
    airdrik:
    big picture thinker:
    Don't know why the entire validation is regex. You could use it for parts, but I think it would be better to split the year, month, and date parts and then perform some procedural logic on those parts.

    Absolutely, and who could argue with code that looks like this:

    def valiDate(dateStr):
    """Checks that the given date string matches...
    [snip]
    return False

    Procedural code is so much better than Regexes

    Comprehension failure.
  • Franz Kafka 2012-04-20 14:22
    Nagesh:
    Regex is only used to show off knowhow. In real life program I am yet to find any good use for it.


    I use it regularly (heh). But then, perl makes it easy.
  • Jay 2012-04-20 14:29
    Peter:
    KattMan:
    Let regex do what it does best, validate the PATTERN matches one of the following: "99/99/9999", "99-99-9999", "9999/99/99" or "9999-99-99", this is easy and accounts for day, month or year first.
    Does this mean that you think 1/1/2012 (say) should be rejected as invalid?


    My bank's website says that dates should be entered in the from "mm/dd/yyyy". And they mean it: If you enter a single digit for the month or the day, they reject the date as invalid.
  • ObiWayneKenobi 2012-04-20 15:15
    Rajendra Kumar:
    Dearest Pros,
    I am needing of program just like this. Only it should be having ANSI C99 codes. I am team leader at major South Asian company and it is important this be delivered to my direct reports. That way I can get back to drinking chai and smoking fags. Plz send to Rajkum@gmail.biz, it's URGENT!


    Nagesh's manager?
  • international smoking pedant 2012-04-20 16:07
    ObiWayneKenobi:
    Rajendra Kumar:
    Dearest Pros,
    I am needing of program just like this. Only it should be having ANSI C99 codes. I am team leader at major South Asian company and it is important this be delivered to my direct reports. That way I can get back to drinking chai and smoking bidis. Plz send to Rajkum@gmail.biz, it's URGENT!


    Nagesh's manager?


    fixed some smoking shit
  • Remy Martin 2012-04-20 16:18
    Dear sirs and madams,

    I regret to inform you of the untimely passing of Alex for the third time this week. As I will now be souly responsible for the content of this site, you can expect one article per week from this point forward. As I am lazy, however, I will not be changing the name.

    Sincerely yours,

    Remy Martin
  • It's a Cock! It's a Fist! It's Zunerman! 2012-04-20 16:23
    Remy Martin:
    Dear sirs and madams,

    I regret to inform you of the untimely passing of Alex for the third time this week. As I will now be souly responsible for the content of this site, you can expect one article per week from this point forward. As I am lazy, however, I will not be changing the name.

    Sincerely yours,

    Remy Martin
    What's with putting "sirs" first? Any true gentleman makes sure his lady comes first.

    Before gagging her with his cock
  • FatherStorm 2012-04-20 16:42
    The Mr. T Experience:
    Zylon:
    Annon:
    frist (this is not spam)

    Wrong on both counts.
    Wow. Your so inciteful.

    I see what you did there...
    (Captcha: quibus -- dative and ablative plural of qui)
  • Friedrice The great 2012-04-20 18:46
    It's a Cock! It's a Fist! It's Zunerman!:
    Remy Martin:
    Dear sirs and madams,

    I regret to inform you of the untimely passing of Alex for the third time this week. As I will now be souly responsible for the content of this site, you can expect one article per week from this point forward. As I am lazy, however, I will not be changing the name.

    Sincerely yours,

    Remy Martin
    What's with putting "sirs" first? Any true gentleman makes sure his lady comes first.

    Before gagging her with his cock


    Then "Remy" would have to come first.
  • AN AWESOME CODER 2012-04-21 12:28
    After reading the comments, I've realized somthing. Some of you think way too hard about the solution and it's shittiness, without knowing the problem.

    There are really only 3 problems with this WTF, in descdending order:

    1.) It doesn't account for 10th and 20th dates (someone mentioned this earlier, I didn't confirm)
    2.) It's a huge hard to maintain regex


    the dates thing comes first, because it means that #2 is true for no reason. You can't even say "at least it works".



    As far as it not detecting EVERY leap year, or not thinking < 1900 or > 2100 or dates, that doesn't matter. What if this code isn't to validate that ANY date is correct? It could be validating dates of jobs that this company has taken, which was founded in 2006. That means any job date before then is bad user input even if it's a valid date, and any date too far in the future is also _probably_ bad.

    In the above case, the programmer made an assumption that any date this code would ever process should never be from the next century. I see no problem with that... if this crap code is still being used 90 years from now to validate order dates, something more major is wrong. Of course, it means in 2012 I can still enter a job with a date of 2080, which is bogus.


    WITH THAT SAID, it's still a WTF. But some of your solutions would actually be less effective at solving the problem, if the case is what I described above. Just use a date library.

  • PiisAWheeL 2012-04-22 14:40
    Oblig:
    You have a problem.

    You decide to use a regex.

    Now you have 00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96 problems.
    Wrong. You now you have 04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96 problems.
  • L. 2012-04-23 04:17
    Re: Simple Date Validation:
    Typical WTF idiocy responses (at least those that weren't trolls). Validating a date is a two step operation. First, parse the string into numbers for month, day, and year. Second, ensure that the month, day, and year are a valid date. Trying to cram a two part operation into a single line is a guaranteed source of WTFs, typically done by programmers who got A's on all of their homework problems but are complete disaster's when it comes to real work on production systems.


    Show me on the doll where the programmers who got A's touched you.
  • abdullah 2012-04-23 10:46
    Shut up foo':
    The Mr. T Experience:
    Zylon:
    Annon:
    frist (this is not spam)

    Wrong on both counts.
    Wow. Your so inciteful.


    It's "You're" and "insightful". Maybe you need a regex spell-checker.


    You missed the point, obvious troll is trying to incite the grammar nazis.
  • PiisAWheeL 2012-04-23 14:49
    AN AWESOME CODER:
    After reading the comments, I've realized somthing. Some of you think way too hard about the solution and it's shittiness, without knowing the problem.

    There are really only 3 problems with this WTF, in descdending order:

    1.) It doesn't account for 10th and 20th dates (someone mentioned this earlier, I didn't confirm)
    2.) It's a huge hard to maintain regex


    the dates thing comes first, because it means that #2 is true for no reason. You can't even say "at least it works".



    As far as it not detecting EVERY leap year, or not thinking < 1900 or > 2100 or dates, that doesn't matter. What if this code isn't to validate that ANY date is correct? It could be validating dates of jobs that this company has taken, which was founded in 2006. That means any job date before then is bad user input even if it's a valid date, and any date too far in the future is also _probably_ bad.

    In the above case, the programmer made an assumption that any date this code would ever process should never be from the next century. I see no problem with that... if this crap code is still being used 90 years from now to validate order dates, something more major is wrong. Of course, it means in 2012 I can still enter a job with a date of 2080, which is bogus.


    WITH THAT SAID, it's still a WTF. But some of your solutions would actually be less effective at solving the problem, if the case is what I described above. Just use a date library.

    Waiting to see how long it would take for someone who can count to read your comment?
  • Jay 2012-04-23 15:11
    PiisAWheeL:
    AN AWESOME CODER:
    After reading the comments, I've realized somthing. Some of you think way too hard about the solution and it's shittiness, without knowing the problem.

    There are really only 3 problems with this WTF, in descdending order:

    1.) It doesn't account for 10th and 20th dates (someone mentioned this earlier, I didn't confirm)
    2.) It's a huge hard to maintain regex


    the dates thing comes first, because it means that #2 is true for no reason. You can't even say "at least it works".



    As far as it not detecting EVERY leap year, or not thinking < 1900 or > 2100 or dates, that doesn't matter. What if this code isn't to validate that ANY date is correct? It could be validating dates of jobs that this company has taken, which was founded in 2006. That means any job date before then is bad user input even if it's a valid date, and any date too far in the future is also _probably_ bad.

    In the above case, the programmer made an assumption that any date this code would ever process should never be from the next century. I see no problem with that... if this crap code is still being used 90 years from now to validate order dates, something more major is wrong. Of course, it means in 2012 I can still enter a job with a date of 2080, which is bogus.


    WITH THAT SAID, it's still a WTF. But some of your solutions would actually be less effective at solving the problem, if the case is what I described above. Just use a date library.

    Waiting to see how long it would take for someone who can count to read your comment?


    There are 3 kinds of people in the world: those who can count, and those who can't.
  • Jay 2012-04-23 15:11
    abdullah:
    Shut up foo':
    The Mr. T Experience:
    Zylon:
    Annon:
    frist (this is not spam)

    Wrong on both counts.
    Wow. Your so inciteful.


    It's "You're" and "insightful". Maybe you need a regex spell-checker.


    You missed the point, obvious troll is trying to incite the grammar nazis.


    He's very incitefull: he's always inciting trouble.
  • PiisAWheeL 2012-04-23 16:38
    Jay:
    PiisAWheeL:
    AN AWESOME CODER:
    Snipped for space...
    Waiting to see how long it would take for someone who can count to read your comment?
    There are 3 kinds of people in the world: those who can count, and those who can't.
    Or the 10 types, the ones who understand binary and the ones who don't?
  • L. 2012-04-24 04:09
    PiisAWheeL:
    Jay:
    PiisAWheeL:
    AN AWESOME CODER:
    Snipped for space...
    Waiting to see how long it would take for someone who can count to read your comment?
    There are 3 kinds of people in the world: those who can count, and those who can't.
    Or the 10 types, the ones who understand binary and the ones who don't?

    Or the 99 types, because stfu ?
  • daef 2012-04-26 03:43
    It's a Cock! It's a Fist! It's Zunerman!:

    What's with putting "sirs" first? Any true gentleman makes sure his lady comes first.

    Before gagging her with his cock

    i see what you did there :-)

    captcha: suscipere
  • Sorpigal 2012-05-04 11:46
    I recommend that you read up on perl6 and specifically perl6 grammars and rules.

    Example lifted from wikipedia:


    token word { \w+ }
    rule phrase { <word> [ \, <word> ]* \. }
    if $string ~~ / <phrase> \n / {
    ...
    }
  • cousteau 2012-07-08 14:43
    That 20(00|04|08|12|16|20|24|28|32|36|40|44|48|52|56|60|64|68|72|76|80|84|88|92|96) must have something to do with leap years. Yeah, some basic algebraic operations would have been fine too, but that's cooler.