views:

153

answers:

5

How do I split a date that is of the form YYYYMMDD into its constituents?

my ($yyyy, $mm, $dd) = $date =~ /(\4d+)(\2d+)(\2d+)/;
+5  A: 
my ($year, $month, $day) = $date =~ /^(\d{4})(\d{2})(\d{2})\z/
    or die "bad date: $date";
ysth
What is the z for?
syker
maybe `$` was meant instead of `\z`?
jdehaan
What would $ mean then?
syker
Could i use o instead? I'm using it two other times (not in a loop though)
syker
@syker: please see [perldoc perlre](http://perldoc.perl.org/perlre.html) for details about regular expression syntax (e.g. what the z, $, \d and other components mean).
Ether
@syker: @jdehaan: `$` would mean either the end of the string or \n and then the end of the string. Since the specified format shouldn't have a \n, I used \z
ysth
@syker: o isn't relevant here - I don't understand what you are proposing it replace
ysth
+4  A: 
#!/usr/bin/perl -w

use strict;

   sub main{
      my $date = "some text with the numbers 2010063011 and more text";
      print "Input Date: $date\n";

      my ($year, $month, $day) = $date =~ /\b(\d{4})(\d{2})(\d{2})\b/;      
      print qq{
               Date:  $date
               Year:  $year
               Month: $month
               Day:   $day\n} if (defined $year && defined $month && defined $day);
   }

   main();

notice this will look for the first date in the regex, it won't work with 2010063011 because it's not a date, but it will work with 20100630, which is what you want.

vol7ron
your method vs the unpack method makes sense, thanks for adding that comment in the `unpack` answer
Armando
+11  A: 
my ($year, $month, $day) = unpack "A4A2A2", $date;

pack and unpack are underused builtins that can be used to great power.

Leon Timmermans
unpack is the fastest perl has to offer, especially for fixed-width data.
vol7ron
can you do error checking with unpack? for ex: have an or 'die "Wrong format"' statement after that?
syker
@syker there's no law against reading the documentation.
hobbs
great power but poor validation
ysth
@ysth: using a regexp doesn't properly validate either. It will allow 9999-99-99 as a date, even though that clearly isn't a valid date.
Leon Timmermans
It depends on how `$date` is being stored, `unpack` is only good for fixed width. Given my example, if there's any other text other than 8 digits (even spaces), then `unpack` will break. That's why my answer adds some pre-validation, using `\b`.
vol7ron
@Leon Timmermans: yes, but it's a good first step; at least you know your variables are numeric can treat them as such.
ysth
A: 

Note that \d matches any Unicode digits, not just latin decimal digits.

So if you want to do input validation use '[0-9]' instead of '\d'.

dolmen
A: 

Whenever I need to work with dates I use the DateTime module. You can grab it from CPAN.

Proclus