2011-11-22 16 views
5

Ho questo formato data ora nella stringa "11:56:41, 22/11/2011".Come confrontare la data della stringa in perl?

Ecco quello che voglio:

confrontare due stringhe di tempo data come.

$date1 = "11:56:41, 11/22/2011"; 
$date2 = "11:20:41, 11/20/2011"; 
if($date2 < $date1) { 
    do something... 
} else { 
    do nothing... 
} 

Qualche idea come potrei ottenere questo in perl?

risposta

11

Un metodo efficace è riordinare i campi a qualcosa di lessicamente comparabile.

sub to_comparable { 
    my ($date) = @_; 
    my ($H,$M,$S,$d,$m,$Y) = $date =~ m{^([0-9]{2}):([0-9]{2}):([0-9]{2}), ([0-9]{2})/([0-9]{2})/([0-9]{4})\z} 
     or die; 
    return "$Y$m$d$H$M$S"; 
} 

if (to_comparable($date2) lt to_comparable($date1)) { 
    ... 
} else { 
    ... 
} 
+3

poiché non sappiamo dalla domanda se il giorno/mese/ora/minuto a cifra singola sarà riempito a zero, potrebbe essere meglio restituire sprintf ('% 04d% 02d% 02d% 02d% 02d $ 02d' , $ Y, $ m, $ d, $ H, $ M, $ S) – bigiain

+0

@ikegami Grazie! questa è la risposta più semplice e ha funzionato! – quinekxi

+0

@bigiain Ho riscontrato un piccolo problema, solo una semplice domanda (immagino che non ce ne sia bisogno di farne un altro) e se la data che stavo per confrontare fosse una non imbottita? – quinekxi

1

Converti i dati di data (nel tuo caso si tratta di datet locali perché non hanno fusi orari) in ISO8601, quindi puoi fare un confronto regolare tra stringhe.

Per effettuare una conversione, è necessario estrarre i componenti sei dal formato

HH:MM:SS, mm/DD/YYYY 

e rimontarli in ISO 8601:

YYYY-MM-DDTHH:MM:SS 

Poi un normale confronto lessicografico funzionerà.

Vedi http://codepad.org/berle9um

qui ripetute:

sub my_format_to_iso8601 { 
    $_[0] =~ /(\d\d):(\d\d):(\d\d), (\d\d)\/(\d\d)\/(\d\d\d\d)/; 
    return "$6-$4-$5T$1:$2:$3"; 
} 

$date1 = "11:56:41, 11/22/2011"; 
$date2 = "11:20:41, 11/20/2011"; 
$d1 = my_format_to_iso8601($date1); 
$d2 = my_format_to_iso8601($date2); 
print "first is $d1\n"; 
print "second is $d2\n"; 
if ($d2 < $d1) { 
    print "second is earlier\n"; 
} else { 
    print "first is earlier\n"; 
} 

ADDENDUM codice Perl di

  • Ikegami è molto meglio.
  • Una libreria di date sarebbe tuo amico qui; basta specificare una stringa di formato e utilizzare la funzione di analisi della libreria per ottenere l'oggetto data, che dovrebbe quindi essere in grado di confrontare direttamente. (Detto questo, è sempre divertente sottolineare che ISO8601 è, per definizione, ordinabile in forma di stringa.)
+0

grazie, sicuramente funziona per me. non c'è una grande differenza tra il tuo codice e quello di ikegami. entrambi hanno funzionato bene. : D – quinekxi

1

In questo caso ho sempre usato Date::Calc:

use Date::Calc; 

my $date1 = "11:56:41, 11/22/2011"; 
my $date2 = "11:20:41, 11/20/2011"; 

my @date1arr=split /[^\d]/, $date1 if($date1 =~ m!\d{2}:\d{2}:\d{2}, \d{2}/\d{2}/\d{4}!; 
my @date2arr=split /[^\d]/, $date2 if($date2 =~ m!\d{2}:\d{2}:\d{2}, \d{2}/\d{2}/\d{4}!; 

my @diff = Delta_DHMS(@date1arr, @date2arr); 
my $less; 
foreach my $d (@diff) { $less = 1 if $d < 0; } 

if($less) { ... } 
+0

Funziona, ma Date :: Calc è abbastanza pesante per il caso semplice qui. la soluzione di ikegami funziona (almeno nello spazio ristretto del problema fornito nella domanda) altrettanto bene senza dover caricare tutto Data :: Calc (un forse insignificante ~ 300 o così ms sulla mia macchina qui ...) – bigiain

12

più Una soluzione che utilizza i confronti sovraccarico dopo la conversione dei tempi di Time::Piece oggetti. Creare oggetti può essere eccessivo per qualcosa di semplice, ma può diventare molto utile se devi fare altre cose con i tempi.

use Time::Piece; 

my $dateformat = "%H:%M:%S, %m/%d/%Y"; 

my $date1 = "11:56:41, 11/22/2011"; 
my $date2 = "11:20:41, 11/20/2011"; 

$date1 = Time::Piece->strptime($date1, $dateformat); 
$date2 = Time::Piece->strptime($date2, $dateformat); 

if ($date2 < $date1) { 
    do something... 
} else { 
    do nothing... 
} 
+1

+1 per [Time :: Piece] (https://metacpan.org/module/JHI/perl-5.7.2/ext/Time/Piece/Piece.pm), un modulo di gestione della data che è già incorporato in Perl –

5

Che, già 4 ore e non un singolo DateTime (Tutti acclamano il possente DateTime) risposta in vista? Stai rallentamento, abbonati ... ☻

use DateTime::Format::Strptime qw(); 
my $p = DateTime::Format::Strptime->new(pattern => '%T, %D', on_error => 'croak',); 

my $date1 = $p->parse_datetime('11:56:41, 11/22/2011'); 
my $date2 = $p->parse_datetime('11:20:41, 11/20/2011'); 

if($date2 < $date1) { 
    say "$date2 comes before $date1"; 
} else { 
    say "$date2 does not come before $date1"; 
} 

Il metodo parse_datetime restituisce le istanze di DateTime cui confronto gli operatori e in stringa sono sovraccarichi di DTRT.

+0

funziona ma senza riserve, i miei requisiti sono che non userò un modulo installato ad eccezione di quello già presente nel pacchetto di installazione di perl. in ogni modo. grazie per il tuo contributo: D – quinekxi

+0

Hail the Mighty DateTime! –

+1

Perché è eccessivo per il lavoro a portata di mano. – ikegami

2

Io uso unixtime.:)

ho convertire entrambe le volte per unixtime e poi devo solo due interi per confrontare e così posso utilizzare gli operatori <, ==,> ecc

esempio convertire in unixtime come segue

my $timestamp = "2014-03-25 12:33:32"; # (We assume localtime) 

# 
# To split on the space character, it's best to use the regex// 
# 
my ($date, $time) = split (/ /, $timestamp); 
my ($year, $mon, $mday) = split ('-', $date); 
my ($hour, $min, $sec) = split (':', $time); 

my $unixtime = timelocal($sec, $min, $hour, $mday, $mon-1, $year); 
Problemi correlati