Home > OS >  (Perl) How to turn string into date format and find most recent?
(Perl) How to turn string into date format and find most recent?

Time:10-11

I'm using Perl and have an input file with multiple dates such as 17/04/2021 written in it as text. How could I go about turning them into date formats and then comparing them to see which one is the most recent?

Input file format:

01/09/2020
23/10/2019
12/06/2022
15/08/2017

Perl Script:

#! /usr/bin/perl
use warnings;
use strict;
use Data::Dumper;

my $InputFile = "path/to/file.input";
open(FH, '<', $InputFile) or die $!;
while(my $Line = <FH>)
{

}
close(FH);

Thanks.

CodePudding user response:

strftime is (always) your friend:

#!/usr/bin/env perl
# Sort timestamps

use 5.12.10;
use Time::Piece;

my $fmt='%d/%m/%Y';
my @t;
while( <DATA> ){
    chop;  # Delete newline
    eval { push @t, Time::Piece->strptime($_, $fmt) } or say "Unexpected input: $_";
}

say $_->strftime($fmt) foreach sort @t;

__DATA__
01/09/2020
23/10/2019
12/06/2022
15/08/2017

CodePudding user response:

Here's one way:


#! /usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
use Time::Local;

my $InputFile = $ARGV[0];
open(my $fh, '<', $InputFile) or die $!;

## A hash to hold the times so we can sort later
my %seconds;

while(my $Line = <$fh>){
  chomp($Line);
  my ($day, $month, $year) = split(/\//, $Line);
  my $secondsSinceTheEpoch = timelocal(0, 0, 0, $day, $month-1, $year);
  $seconds{$secondsSinceTheEpoch}  
}
close($fh);

my @sortedSeconds = sort {$a <=> $b} keys(%seconds);
print "$sortedSeconds[0]\n";
    

Or, if you're into the whole brevity thing:

#! /usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
use Time::Local;

## A hash to hold the times so we can sort later
my %seconds;

while(<>){
  chomp();
  my ($day, $month, $year) = split(/\//);
  $seconds{timelocal(0, 0, 0, $day, $month-1, $year)}  
}

my @sortedSeconds = sort {$a <=> $b} keys(%seconds);
print "$sortedSeconds[0]\n";

In both cases, you need to pass the file to the script as an argument:

$ foo.pl file
1502744400

CodePudding user response:

Dates in the format yyyymmdd can be just compared directly, numerically or lexically. So turn it around

use warnings;
use strict;
use feature 'say';
# use List::Util qw(max);

my @dates;

while (<>) {
    chomp;

    push @dates, join '', reverse split '/';
}

@dates = sort { $a <=> $b } @dates;  # latest: $dates[-1]

say for @dates;

# Or, if only the last one is needed (uncomment 'use' statement)
# my $latest_date = max @dates;

The "diamond operator" <> reads line by line files submitted on the command line, when used in scalar context. The split argument for the separator is still a regular expression even as I use '' delimiters instead of /\//, for convenience. (Its other argument is by default $_ variable.) Also see reverse, join, sort, and List::Util, as needed.

Can do it in a commnad-line program ("one-liner") as well

perl -wnlE'push @d, join "", reverse split "/"; }{ say for sort @d' file

where }{ stands for the beginning of END { } block. Or

perl -MList::Util=max -wnlE'... }{ say max @d' file

If you'd like it more compact,

use warnings;
use strict;
use feature 'say';

say for sort  map { chomp; join '', reverse split '/' } <>;

That same diamond operator in the list context returns all lines at once.

Or on the command line

perl -wE'say for sort  map { chomp; join "", reverse split "/" } <>' file
  • Related