0

I am using perl to access a DB from where I am getting the date in DD-MON-YYYY format. I need to perform 2 operations:

  1. Convert this format to a MM/DD/YYYY format.
  2. Compare this date with two dates to see if it lies in that time range.

    my $chdate = '15-Feb-2013';

    sub get_stats {

    my %map = ( 'Jan' => '01', 'Feb' => '02', 'Mar' => '03', 'Apr' => '04',
                'May' => '05', 'Jun' => '06', 'Jul' => '07', 'Aug' => '08',
                'Sep' => '09', 'Oct' => '10', 'Nov' => '11', 'Dec' => '12');
    
        $chdate =~ s/(..)-(...)-(....)/$map{$2}\/$1\/$3/;
        print "New date: $chdate";
    

    }

How do I perform the (2) operation?

I have an old version of Perl (no Time::Piece module), which I do not have privileges to update :)

Pascal Belloncle
  • 11,184
  • 3
  • 56
  • 56
adizone
  • 203
  • 1
  • 5
  • 13

3 Answers3

5

I suggest you use the Time::Piece module. It has been a core module since Perl5 v9.5 and so probably won't need installing.

Just decode the date using strptime and reencode it using strftime.

use strict;
use warnings;

use Time::Piece;

my $date = '28-jul-1986';

print Time::Piece->strptime($date, '%d-%b-%Y')->strftime('%m/%d/%Y');

output

07/28/1986
Borodin
  • 126,100
  • 9
  • 70
  • 144
  • Unfortunately I am using perl-5.8.6, and it complains about Time::Piece module. – adizone Mar 04 '13 at 13:07
  • 1
    You *really* should update your version of Perl. v8.6 is over eight years old and there have been four major releases since then. Are you able to install `Time::Piece` from CPAN? I see no reason why it shouldn't work on your system. – Borodin Mar 04 '13 at 14:45
  • I am using perl from a server, don't have the privileges to update the version. I found a novice way to make the conversion :) – adizone Mar 08 '13 at 01:31
1

If you convert your dates to Time::Piece object then you can compare them using the standard numeric comparison operators. So you could do something like this.

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;

use Time::Piece;

my $start_date_str = '1-mar-2013';
my $end_date_str   = '31-mar-2013';
my $date_to_test_str = '4-mar-2013';

my $in_fmt  = '%d-%b-%Y';
my $out_fmt = '%m/%d/%y'; # Warning: Illogical format!

my $start_date_tp = Time::Piece->strptime(
  $start_date_str, $in_fmt
);
my $end_date_tp = Time::Piece->strptime(
  $end_date_str, $in_fmt
);
my $date_to_test_tp = Time::Piece->strptime(
  $date_to_test_str, $in_fmt
);

print $date_to_test_tp->strftime($out_fmt), ' is ';
unless ($start_date_tp <= $date_to_test_tp and
    $date_to_test_tp <= $end_date_tp) {
      print ' not ';
}
say 'between the two test dates';
Dave Cross
  • 68,119
  • 3
  • 51
  • 97
-2

For (2) you can do this:

sub dateAsNumber # Arg mm/dd/yyyy - Converts to a number to be compared
{
   $_[0]=~m%(\d\d)/(\d\d)/(\d\d\d\d)%;
   return (($3 * 400 + $1) * 40 + $2);
}

$test = &dateAsNumber($testDateAsString);

if (&dateAsNumber($startDateAsString) < $test &&
    &dateAsNumber($endDateAsString) > $test)
{
   print "$test date is between $startDateAsString and $endDateAsString\n";
}
else
{
   print "$test date is NOT between $startDateAsString and $endDateAsString\n";
}
Ed Heal
  • 59,252
  • 17
  • 87
  • 127
  • how did you determine (($3 * 400 + $1) * 40 + $2) formula? – adizone Mar 11 '13 at 18:53
  • You just need to compare two numbers - There are no more than 400 days in the year or 40 days in the month (I rounded up). Does not matter if there are gaps in the number line. – Ed Heal Mar 11 '13 at 21:05
  • Thanks Ed. Just a comment, shouldn't the regex be modified as: $_[0] =~ /(\d\d)\/(\d\d)\/(\d\d\d\d)/; – adizone Mar 11 '13 at 21:52
  • @aditya iIn Perl (if memory serves me right) you can use anything for the pattern delimiter. Corrected it though - See http://stackoverflow.com/questions/5770590/which-characters-can-be-used-as-regular-expression-delimiters – Ed Heal Mar 12 '13 at 04:30
  • Wouldn't `$3 . $1 . $2` work just as well as your overcomplicated formula? – Dave Cross Mar 10 '16 at 17:26