coldfingertips has asked for the wisdom of the Perl Monks concerning the following question:

I can only get it to jump on the first $month test. No matter what I choose, I can't get the last two $month checks to pick anything up. Is there a problem with my syntax?
if (($month eq "01" && $day > 29) || ($month eq "09" && $day > 30) || +($month eq "11" && $day > 30))

janitored by ybiC: Rename from less-than-descriptive "Syntax problem", for searchability

Replies are listed 'Best First'.
Re: Roll your own date validation
by Corion (Patriarch) on Jan 09, 2004 at 09:53 UTC

    Are you sure that $month always has two digits? You are using string comparision for comparing $month to a number, and I find that counterintuitive.

    Also, something with your calculations seems weird. Traditionally, month numbers are zero based in Perl, and most functions treat them as such. December will always have 31 days, but you limit it to 30 days, and similarly October. Or your January check makes not much sense, since January can well have more than 29 days, in most cases it even has 31 days.

    perl -MHTTP::Daemon -MHTTP::Response -MLWP::Simple -e ' ; # The $d = new HTTP::Daemon and fork and getprint $d->url and exit;#spider ($c = $d->accept())->get_request(); $c->send_response( new #in the HTTP::Response(200,$_,$_,qq(Just another Perl hacker\n))); ' # web
      Am I sure the month will always be two digits? Yes, I'm 100% positive and from the snippet below, it'll also relieve your wonders on why I'm comparing to a number.

      With all that beside us now, can someone help me setup the max day checker?

      print <<"ALL"; Day: <SELECT NAME="day" SIZE="1"> <OPTION SELECTED> $editday <OPTION> 01 <OPTION> 02 <OPTION> 03 <OPTION> 04 <OPTION> 05 <OPTION> 06 <OPTION> 07 <OPTION> 08 <OPTION> 09 <OPTION> 10 <OPTION> 11 <OPTION> 12 <OPTION> 13 <OPTION> 14 <OPTION> 15 <OPTION> 16 <OPTION> 17 <OPTION> 18 <OPTION> 19 <OPTION> 20 <OPTION> 21 <OPTION> 22 <OPTION> 23 <OPTION> 24 <OPTION> 25 <OPTION> 26 <OPTION> 27 <OPTION> 28 <OPTION> 29 <OPTION> 30 <OPTION> 31 </SELECT> Month: <SELECT NAME="month" SIZE="1"> <OPTION SELECTED> $editmonth <OPTION> 01 <OPTION> 02 <OPTION> 03 <OPTION> 04 <OPTION> 05 <OPTION> 06 <OPTION> 07 <OPTION> 08 <OPTION> 09 <OPTION> 10 <OPTION> 11 <OPTION> 12 </select> Year: <SELECT NAME="year" SIZE="1"> <OPTION SELECTED> $edityear <OPTION>04 <OPTION> 05 <OPTION> 06 </select> </td></tr> <tr><td>Course:</td><td> <SELECT NAME="course" SIZE="1"> <OPTION SELECTED> $course <OPTION>GDP Mod 1 <OPTION>GDP Mod 2 <OPTION>GDP Mod 3 <OPTION>GDP Mod 4 <OPTION> <OPTION>HYG Mod 1 <OPTION>HYG Mod 2 <OPTION>HYG Mod 3 <OPTION> <OPTION>Carers Sp. Needs <OPTION>VDP <OPTION>CDP Sp Needs <OPTION> <OPTION>TBC <OPTION>Lecture Day <OPTION>Other </SELECT>

        I would do the comparision numerically, because you are, in fact, comparing numbers.

        Are you really really sure, that your $month does match /^\d{2}$/ ? Because your OPTION fields seem to contain a space before the number, and I am not really sure whether browsers will strip that space.

        For me, your original code works without and problem and I am able without further problem to trigger any of the three conditions.

        So I can only recommend really closely checking your input (for example by using the mentioned CGI::Untaint::date, and/or Time::Local). And also revisit your date/time math, as the month you associate with the number 1 will always have 31 days, and not 29 days, even though you cut it off there.

        Personally, to make sure an entered date exists, I would use Time::Local, which throws an error for invalid day/month/year combinations.

        perl -MHTTP::Daemon -MHTTP::Response -MLWP::Simple -e ' ; # The $d = new HTTP::Daemon and fork and getprint $d->url and exit;#spider ($c = $d->accept())->get_request(); $c->send_response( new #in the HTTP::Response(200,$_,$_,qq(Just another Perl hacker\n))); ' # web
Re: Roll your own date validation
by dragonchild (Archbishop) on Jan 09, 2004 at 14:35 UTC
    There is no reason to roll this code yourself. None. Use one of the many, many excellent date/time modules on CPAN. For example, if you were to use Date::Calc for this, it would go something like:
    use Date::Calc qw( Days_In_Month ); if ($days > Days_In_Month($year, $month)) { # Bitch and moan }

    You will need to supply the year, because February changes how many days it has, depending on the year. (It's fickle like that.)

    ------
    We are the carpenters and bricklayers of the Information Age.

    Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

      I totally agree with dragonchild about using Date::Calc for date checking and calculation. It greatly simplifies things, and eliminates some subtle and sometimes obscure errors (like checking leap years as above).

      (geez, repeat of
      Re: Re: Re: Re: Re: Calculating between times? :-)
Re: Roll your own date validation
by elbow (Scribe) on Jan 09, 2004 at 10:22 UTC
    I agree with Corion.

    Try changing your statement to :-

    if (($month == 1 && $day > 29) || ($month == 9 && $day > 30) || ($month == 11 && $day > 30))

    This allows you to match '09' (as well as 9)

    elbow
Re: Roll your own date validation
by zby (Vicar) on Jan 09, 2004 at 10:42 UTC
    If you want to validate a date there is a CPAN module CGI::Untaint::date. I can't say how usefull it is - I never used it.
Re: Roll your own date validation
by chimni (Pilgrim) on Jan 09, 2004 at 10:19 UTC

    Are you parsing the output of `date` to get your $month.
    Fri Jan 9 15:25:55 IST 2004
    As you can see the month part is not a 2 digit string .
    You can put some check with the following logic
    if($month < 10){$month=0.$month};
    HTH