Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:
Hello monks!
If you have a series of dates in a file, like:
06/30/96
08/07/97
09/05/97
12/11/97
03/26/98
07/17/98
10/23/98
11/12/98
01/14/99
04/10/99
05/27/99
02/10/00
03/10/00
03/15/00
03/15/00
03/30/00
06/15/00
07/13/00
08/03/00
09/07/00
09/30/00
12/10/00
01/25/01
02/27/01
sorted from the oldest to the newest, is there a quick way of comparing all dates against the oldest and print the oldest and then the differences of all others in months when compared with the oldest?
Thank you
Re: compare dates?
by derby (Abbot) on Apr 09, 2008 at 17:35 UTC
|
#!/usr/bin/perl
use strict;
use warnings;
use Date::Manip;
my @dates;
while( <DATA> ) {
chomp;
push( @dates, ParseDate( $_ ) );
}
@dates = sort @dates;
my $oldest = $dates[0];
foreach my $current ( @dates ) {
my $diff = DateCalc( $oldest, $current );
print "Diff between ",
UnixDate( $oldest, "%m/%d/%y" ),
" and ",
UnixDate( $current, "%m/%d/%y" ),
" is ",
Delta_Format( $diff, "approx", 0, "%Mt" ),
"\n";
}
__DATA__
06/30/96
08/07/97
09/05/97
12/11/97
03/26/98
07/17/98
10/23/98
11/12/98
01/14/99
04/10/99
05/27/99
02/10/00
03/10/00
03/15/00
03/15/00
03/30/00
06/15/00
07/13/00
08/03/00
09/07/00
09/30/00
12/10/00
01/25/01
02/27/01
Update: If the list is all ready sorted (and you need a bit of golf)
#!/usr/bin/perl
use strict;
use warnings;
use Date::Manip;
use List::Util qw( reduce );
my @dates = qw( 06/30/96 08/07/97 09/05/97 12/11/97 03/26/98
07/17/98 10/23/98 11/12/98 01/14/99 04/10/99
05/27/99 02/10/00 03/10/00 03/15/00 03/15/00
03/30/00 06/15/00 07/13/00 08/03/00 09/07/00
09/30/00 12/10/00 01/25/01 02/27/01 );
reduce {
print "Diff between $a and $b is ", Delta_Format( DateCalc( $a, $b )
+, "approx", 0, "%Mt" ), "\n";
$a;
} @dates;
| [reply] [d/l] [select] |
|
I was about to rant hey that does not even work, it spits out a ton of warnings, how dare you post such untested code, etc etc.. Then I saw I had an old version of Date::Manip. After upgrading from 5.42 to 5.48 it works flawlessly.
# Date::Manip 5.42
]$ /usr/bin/perl -w 679308.pl
Argument "approx" isn't numeric in numeric gt (>) at /usr/lib/perl5/ve
+ndor_perl/5.8.5/Date/Manip.pm line 1908, <DATA> line 24.
Diff between 06/30/96 and 06/30/96 is 0.000000
Argument "approx" isn't numeric in numeric gt (>) at /usr/lib/perl5/ve
+ndor_perl/5.8.5/Date/Manip.pm line 1908, <DATA> line 24.
Diff between 06/30/96 and 08/07/97 is 0.000000
Argument "approx" isn't numeric in numeric gt (>) at /usr/lib/perl5/ve
+ndor_perl/5.8.5/Date/Manip.pm line 1908, <DATA> line 24.
Diff between 06/30/96 and 09/05/97 is 0.000000
# Date::Manip 5.48
$ /usr/bin/perl 679308.pl
Diff between 06/30/96 and 06/30/96 is 0.000000
Diff between 06/30/96 and 08/07/97 is 13.240246
Diff between 06/30/96 and 09/05/97 is 14.193018
Owners of older versions of Date::Manip are hereby warned.
| [reply] [d/l] [select] |
Re: compare dates?
by apl (Monsignor) on Apr 09, 2008 at 17:12 UTC
|
Take a look at this CPAN module. Operations include < and >, though it looks like you'll have to translate the format of your dates. | [reply] |
Re: compare dates?
by poolpi (Hermit) on Apr 10, 2008 at 09:40 UTC
|
#!/usr/bin/perl -w
use strict;
use DateTime;
my $date = [
qw{
06/30/96
08/07/97
09/05/97
12/11/97
03/26/98
07/17/98
10/23/98
11/12/98
01/14/99
04/10/99
05/27/99
02/10/00
03/10/00
03/15/00
03/15/00
03/30/00
06/15/00
07/13/00
08/03/00
09/07/00
09/30/00
12/10/00
01/25/01
02/27/01 }
];
my $oldest = dt( shift @$date );
printf "Diff in month between %s and \n", $oldest->dmy('/');
printf "%s : %s\n", $_, dt($_)->subtract_datetime($oldest)->in_units(
+'months') for @$date;
sub dt {
my ( $month, $day, $year ) = split /\//, shift;
$year = ( $year > 90 ? '19' : '20' ) . $year;
DateTime->new( year => $year, month => $month, day => $day );
}
Output:
Diff in month between 30/06/1996 and
08/07/97 : 13
09/05/97 : 14
12/11/97 : 17
03/26/98 : 20
07/17/98 : 24
10/23/98 : 27
11/12/98 : 28
01/14/99 : 30
04/10/99 : 33
05/27/99 : 34
02/10/00 : 43
03/10/00 : 44
03/15/00 : 44
03/15/00 : 44
03/30/00 : 45
06/15/00 : 47
07/13/00 : 48
08/03/00 : 49
09/07/00 : 50
09/30/00 : 51
12/10/00 : 53
01/25/01 : 54
02/27/01 : 55
hth, PooLpi
'Ebry haffa hoe hab im tik a bush'. Jamaican proverb
| [reply] [d/l] [select] |
Re: compare dates?
by papidave (Pilgrim) on Apr 10, 2008 at 20:20 UTC
|
If I recall correctly, the date in July of 2000 was pretty nice. I went out to dinner theater, or somesuch. The ones in autumn of '98 were pretty mundane.
At least, I'm hoping that's what you want to know. Because only a cad would compare his date with someone else's.
:) | [reply] |
Re: compare dates?
by Anonymous Monk on Apr 09, 2008 at 17:34 UTC
|
use strict;
use warnings;
my @d = qw[
06/30/96
08/07/97
09/05/97
12/11/97
03/26/98
07/17/98
10/23/98
11/12/98
01/14/99
04/10/99
05/27/99
02/10/00
03/10/00
03/15/00
03/15/00
03/30/00
06/15/00
07/13/00
08/03/00
09/07/00
09/30/00
12/10/00
01/25/01
02/27/01
];
print $$_[0], $/ for sort { my @f = $$a[1] <=> $$b[1]; push @f, $$a[2]
+ <=> $$b[2]; push @f, $$a[3] <=> $$b[3]; return $f[0] if $f[0] != 0;
+return $f[1] if $f[1] != 0; return $f[2]; } map { /(\d+)\D(\d+)\D(\d+
+)/; [$_, $3,$2,$1] } @d;
__END__
08/03/00
09/07/00
02/10/00
03/10/00
12/10/00
07/13/00
03/15/00
03/15/00
06/15/00
03/30/00
09/30/00
01/25/01
02/27/01
06/30/96
09/05/97
08/07/97
12/11/97
11/12/98
07/17/98
10/23/98
03/26/98
04/10/99
01/14/99
05/27/99
| [reply] [d/l] |
|
The Y2K bug has bitten you!
CountZero A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James
| [reply] |
|
Ha, thats what you think :)
To me 00 means 1900, and 99 means 1999
| [reply] |
|
|
|
Some Anonymous Monk writes:
print $$_[0], $/ for sort { my @f = $$a[1] <=> $$b[1]; push @f, $$a[2] <=> $$b[2]; push @f, $$a[3] <=> $$b[3]; return $f[0] if $f[0] != 0; return $f[1] if $f[1] != 0; return $f[2]; } map { /(\d+)\D(\d+)\D(\d+)/; [$_, $3,$2,$1] } @d;
Are you sure you didn't mean to post this in Obfuscated code?
s//----->\t/;$~="JAPH";s//\r<$~~/;{s|~$~-|-~$~|||s
|-$~~|$~~-|||s,<$~~,<~$~,,s,~$~>,$~~>,,
$|=1,select$,,$,,$,,1e-1;print;redo}
| [reply] [d/l] |
|
Why? Theres nothing obfuscated about it.
| [reply] |
|
|