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

Hi Monks,

I am sure I am making this much more difficult than it needs to be but I am struggling to find a simple answer to this.

I don't wish to use bad language, but I am basically looking for the Perl equivalent of DateSerial in Visual Basic (sorry!). I.E. to be able to easily convert a yyyy/mm/dd string into a date.

I have looked into using Date::Manip and Date:Calc but they look too complicated for my needs.

Ultimately I need to read in a date string, add or subtract days, months or years from that date, and convert back to a string.

Your help would be very much appreciated.

Marc

Replies are listed 'Best First'.
Re: Converting string to date
by Abigail-II (Bishop) on Nov 19, 2003 at 17:42 UTC
    Date::Calc and Date::Manip are the way to go though. They do exactly what you need to do. Just don't get bothered by the fact they are capable of doing more.

    Abigail

Re: Converting string to date
by PodMaster (Abbot) on Nov 19, 2003 at 17:53 UTC
    use DateTime; use strict; use warnings; my $str = '2003/11/12'; my( $y, $m, $d ) = qw[ 2003 11 12 ]; # this part magic, use split $d = DateTime->new( year => $y, month => $m, day => $d); warn $d->ymd; $d->add(days => 6); die $d->ymd; __END__ 2003-11-12 at C:\dev\loose\datetime3.pl line 7. 2003-11-18 at C:\dev\loose\datetime3.pl line 9.

    MJD says "you can't just make shit up and expect the computer to know what you mean, retardo!"
    I run a Win32 PPM repository for perl 5.6.x and 5.8.x -- I take requests (README).
    ** The third rule of perl club is a statement of fact: pod is sexy.

Re: Converting string to date
by bart (Canon) on Nov 19, 2003 at 18:01 UTC
    Well if you don't mind a little bit of handywork, you can get along fine with the core module Time::Local. That module implements the functions timelocal() and timegm(), the inverse functions of respectively localtime() and gmtime().

    One thing you should not forget, is to decrement the month value: January is month 0, December month 11. 4-digit years are fine, though you're allowed to subtract 1900.

    Here's some sample code, that calculates the time value for some date, at noon, GMT:

    my $datestring = "2003/11/19"; # input use Time::Local; my($y, $m, $d) = $datestring =~ m<^(\d+)/(\d+)/(\d+)$> or die "Not a valid date"; my $time = timegm(0, 0, 12, $d, $m-1, $y); print "The time value is $time, for " . gmtime($time) . "\n";
    Result:
    The time value is 1069243200, for Wed Nov 19 12:00:00 2003

    p.s. The results are limited to the date range that applies to Unix time, thus to localtime and gmtime, i.e. from 1970 to 2035, roughly; or the equivalent on your platform — on the Mac, that's from 1904 to around 2035.

Re: Converting string to date
by l3nz (Friar) on Nov 19, 2003 at 18:18 UTC
    In the end you'll notice it just takes a couple of lines of code to do it - whatever you may write yourself will be longer and more error prone. See this example:
    use Date::Manip; $main::TZ = "CET"; my $ds = '2003/10/19'; # it's a sunday my $d = &ParseDate( $ds ); print "$ds = $d \n"; my $d2 = &DateCalc( $d,"+ 3hours 12minutes 6 seconds", \$err); print "$d2\n"; my $d3 = &DateCalc( $d,"+ 5 business days", \$err); print "$d3\n";
    Note how you can even use business days when doing date operations (that's why $d3 looks weird at first...). I think it's no point reinventing the wheel. :-)

    On the other side, Date::Manip is big and slow, so if you have to compute thousands or millions of operations with it in a few seconds, it's not likely the way to go....

      Thank you all for your suggestions. I finally got Date::Manip to work and am happily using that. I honestly don't know what I would do without Perl Monks!

      Marc

Re: Converting string to date
by dws (Chancellor) on Nov 19, 2003 at 17:55 UTC
    I am basically looking for the Perl equivalent of DateSerial in Visual Basic ... to be able to easily convert a yyyy/mm/dd string into a date.

    If you're going to be converting multiple date strings during the course of a script run, and if the dates are reasonably well bounded, then another approach is to precalculate a set of   "yyyy/mm/dd" => integer mappings, set them up to load into a hash (e.g., pre-generate a separate .pl file that does nothing except load up a hash, then require that file into your script), then use table lookup to do the conversion. This is less of a space problem than it might seem: 3653 entries covers a ten year span.