Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Matching Date

by Anonymous Monk
on Oct 13, 2006 at 14:15 UTC ( [id://578144]=perlquestion: print w/replies, xml ) Need Help??

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

Hi Monks!

I am trying to fix some display issues with dates, but for some reason I can't figure it out why my code isn't working on today's date, here is what I have, I just can't see where the problem is, and why today's date is matching on L1, since I have to digits starting the first part of the date value, here is the code :

#my $date = "$mon/$mday/$year"; my $date = "10/13/2006"; if ($date=~/(\d{1})\/(\d{2})\/(\d{4})/){ $date="0".$1."\/".$2."\/".$3; print "<br>L1 - $date<br>"; }elsif($date=~/(\d{2})\/(\d{1})\/(\d{4})/) { $date=$1."\/0".$2."\/".$3; print "<br>L2 - $date<br>"; }else{ $date=~/(\d{1})\/(\d{1})\/(\d{4})/; $date="0".$1."\/0".$2."\/".$3; }


Thanks for the Help!!!

formatting cleaned up by GrandFather

Replies are listed 'Best First'.
Re: Matching Date
by blazar (Canon) on Oct 13, 2006 at 14:36 UTC
    I am trying to fix some display issues with dates, but for some reason I can't figure it out why my code isn't working on today's date, here is what I have, I just can't see where the problem is, and why today's date is matching on L1, since I have to digits starting the first part of the date value,

    First, I had some difficulties reading your code. Thus I reformatted it, with no substantial modification:

    my $date = "10/13/2006"; if ($date=~/(\d{1})\/(\d{2})\/(\d{4})/) { $date="0".$1."\/".$2."\/".$3; print "<br>L1 - $date<br>"; } elsif ($date=~/(\d{2})\/(\d{1})\/(\d{4})/) { $date=$1."\/0".$2."\/".$3; print "<br>L2 - $date<br>"; } else { $date=~/(\d{1})\/(\d{1})\/(\d{4})/; $date="0".$1."\/0".$2."\/".$3; # no print here?!? }

    So it seems that you want to "normalize" month and day to two digits. Then I would switch logic altogether:

    my $date = "10/13/2006"; my ($m,$d,$y)=split m(/), $date; $date=join '/', (map sprintf('%02d', $_), $m, $d), $y;

    Update: I don't have the slightest idea of what I was thinking of, but I was reinventing the wheel myself, using awkward logic to implement something that sprintf offers out of the box in the first place:

    my $date = "10/13/2006"; $date=sprintf '%02d/%02d/%d', split m(/), $date;

    Of course this does not do full validation of the initial $date but that's something you can add easily once you have $m, $d and $y. So I don't know why your code "doesn't work" for today's date, but the lesson is, I hope: do not reinvent the wheel!

      This is an alternate version of blazar's solution, which may be slightly easier for new Perl programmers (and possibly future maintenance programmers) to understand:
      #my $date = "$mon/$mday/$year"; my $date = "10/13/2006"; my ($mon,$mday,$year) = split('/',$date); $mon = sprintf("%02d",$mon); $mday = sprintf("%02d",$mday); $date = "$mon/$mday/$year";
      Also, I'd like to point the OP to Date::Calc and Date::Format.

      ---
      It's all fine and dandy until someone has to look at the code.
Re: Matching Date
by Hue-Bond (Priest) on Oct 13, 2006 at 14:41 UTC
    I just can't see where the problem is, and why today's date is matching on L1

    Why shouldn't it? It has a number followed by a slash and then 2 numbers... Maybe you want to anchor the regex to the beginning and end of the string?:

    my @dates = qw| 10/13/2006 1/13/2006 10/1/2006 1/1/2006 |; foreach my $date (@dates) { if ($date =~ m|^(\d{1,2}) / (\d{1,2}) / (\d{4})$|x) { ## <-- anc +horing $date = sprintf "%02d/%02d/%04d", $1, $2, $3; } print "result: <$date>\n"; } __END__ result: <10/13/2006> result: <01/13/2006> result: <10/01/2006> result: <01/01/2006>

    Update: Typo fix.

    --
    David Serrano

Re: Matching Date
by johngg (Canon) on Oct 13, 2006 at 15:03 UTC
    Other Monks have provided solutions to your problem but your OP and some of the replies would, IMHO, be more readable given an alternative choice of regular expression delimiter. Instead of

    $date =~ /(\d\d?)\/(\d\d?)\/(\d{4})/;

    I would prefer

    $date =~ m{(\d\d?)/(\d\d?)/(\d{4})};

    to avoid having to keep escaping the date separators.

    Cheers,

    JohnGG

      here it is:
      if ($date=~/^(\d{1})\/(\d{2})\/(\d{4})$/g){ + $date="0".$1."\/".$2."\/".$3; + print "<br>L1 - $date<br>"; }elsif($date=~/^(\d{2})\/(\d{1})\/(\d{4})/g){ + $date=$1."\/0".$2."\/".$3; + + print "<br>L2 - $date<br>"; }elsif($date=~/^(\d{1})\/(\d{1})\/(\d{4})/g){ + $date="0".$1."\/0".$2."\/".$3; }else{ $date=$date; + }
Re: Matching Date
by RobPayne (Chaplain) on Oct 13, 2006 at 14:42 UTC
    It's not clear exactly what you wanted to happen in the above, but your first pattern was matching because you didn't tell it the pattern needed to start with the first character. Without the ^ that I added, to the beginning of each regex, perl would begin the match wherever it could in the string. You may also want to finish the regex off with a $ so you only match when the entire line matches, depending upon you you are getting your $mon/$mday/$year, with an else for something that really isn't a good match.
    #my $date = "$mon/$mday/$year"; my $date = "10/13/2006"; if ($date=~/^(\d{1})\/(\d{2})\/(\d{4})/) { $date="0".$1."\/".$2."\/".$3; print "<br>L1 - $date<br>\n"; } elsif($date=~/^(\d{2})\/(\d{1})\/(\d{4})/) { $date=$1."\/0".$2."\/".$3; print "<br>L2 - $date<br>\n"; } elsif($date=~/^(\d{2})\/(\d{2})\/(\d{4})/) { $date=$1."\/0".$2."\/".$3; print "<br>L3 - $date<br>\n"; } else{ $date=~/^(\d{1})\/(\d{1})\/(\d{4})/; $date="0".$1."\/0".$2."\/".$3; print "<br>L4 - $date</br>\n"; }
    That prints 'L3 - 10/13/2006' between breaks.
Re: Matching Date
by Skeeve (Parson) on Oct 13, 2006 at 14:43 UTC
    $date=~/(\d{1})\/(\d{2})\/(\d{4})/ This matches 1 digit for month (= "0") and not 2. Better would be:
    $date=~/(\d\d?)\/(\d\d?)\/(\d{4})/
    or, if you want curly braces:
    $date=~/(\d{1,2})\/(\d{1,2})\/(\d{4})/
    or, if you like to check more:
    $date=~/(0?[1-9]|1[0-2])\/(0?[0-9]|[12]\d|3[01])\/(\d{4})/

    s$$([},&%#}/&/]+}%&{})*;#$&&s&&$^X.($'^"%]=\&(|?*{%
    +.+=%;.#_}\&"^"-+%*).}%:##%}={~=~:.")&e&&s""`$''`"e
Re: Matching Date
by fenLisesi (Priest) on Oct 13, 2006 at 17:24 UTC
    Here is a solution with Regexp::Common: which prints:
    01/02/2006 => (01, 02, 2006) => (01, 02, 2006) 1/2/2006 => ( 1, 2, 2006) => (01, 02, 2006) 11/22/2006 => (11, 22, 2006) => (11, 22, 2006) 12/1/2006 => (12, 1, 2006) => (12, 01, 2006) 13/1/2006 => No match 2/35/2006 => No match 1/2/06 => No match
    Hope this helps.

    Update: Added <readmore>

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://578144]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (5)
As of 2024-04-19 07:26 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found