2012-02-03 13 views
10

W programie Perl mam zmienną zawierającą datę/czas w tym formacie:Różnica czasu w sekundach

Feb 3 12:03:20 

muszę stwierdzić, czy ta data jest więcej niż x sekund życia (na podstawie aktualnego czasu), nawet jeśli ma to miejsce po północy (np. Feb 3 23:59:00 z bieżącym czasem = Feb 4 00:00:30).

Znalezione przeze mnie informacje o dacie/godzinie są zadziwiające. W pobliżu, jak mogę powiedzieć, potrzebuję użyć Date::Calc, ale nie znajduję sekundy-delta. Dzięki :)

Odpowiedz

3

W perlu zawsze istnieje więcej niż jeden sposób na zrobienie czegoś. Oto ten, który wykorzystuje tylko moduł, który jest standardowo wyposażony w Perlu:

#! perl -w 

use strict; 
use Time::Local; 

my $d1 = "Feb 3 12:03:20"; 
my $d2 = "Feb 4 00:00:30"; 

# Your date formats don't include the year, so 
# figure out some kind of default. 
use constant Year => 2012; 


# Convert your date strings to Unix/perl style time in seconds 
# The main problems you have here are: 
# * parsing the date formats 
# * converting the month string to a number from 1 to 11 
sub convert 
{ 
    my $dstring = shift; 

    my %m = ('Jan' => 0, 'Feb' => 1, 'Mar' => 2, 'Apr' => 3, 
      'May' => 4, 'Jun' => 5, 'Jul' => 6, 'Aug' => 7, 
      'Sep' => 8, 'Oct' => 9, 'Nov' => 10, 'Dec' => 11); 

    if ($dstring =~ /(\S+)\s+(\d+)\s+(\d{2}):(\d{2}):(\d{2})/) 
    { 
     my ($month, $day, $h, $m, $s) = ($1, $2, $3, $4, $5); 
     my $mnumber = $m{$month}; # production code should handle errors here 

     timelocal($s, $m, $h, $day, $mnumber, Year - 1900); 
    } 
    else 
    { 
     die "Format not recognized: ", $dstring, "\n"; 
    } 
} 

my $t1 = convert($d1); 
my $t2 = convert($d2); 

print "Diff (seconds) = ", $t2 - $t1, "\n"; 

Aby zrobić to naprawdę produkcja gotowe, potrzebuje lepszej obsługi od roku (na przykład, co się stanie, gdy data rozpoczęcia jest w grudniu i na końcu data w styczniu?) i lepszą obsługę błędów (na przykład, co się stanie, jeśli zostanie skasowany skrót 3-znakowy miesiąca?).

+0

wow ... bardziej zaangażowany niż się spodziewałem ... dzięki –

+2

@xivix, jest niepotrzebnie skomplikowany do tego, co chcesz. [Odpowiedź vmpstr] (http://stackoverflow.com/a/9134822/132382) jest całkowicie wykonalny tutaj. – pilcrow

+0

Wszystko zależy od tego, ile modułów możesz użyć. Zobacz odpowiedź @vmpstr, używając Date :: Parse. Jeśli instalacja tego modułu jest akceptowalna, przejdź do niego. Prawdopodobnie wykona lepszą pracę z obsługą różnych formatów danych i możliwych błędów niż ten krótki fragment kodu. – theglauber

9

Wydaje się, że jest wygodnie Date::Parse. Oto przykład:

use Date::Parse; 

print str2time ('Feb 3 12:03:20') . "\n"; 

A oto co wyprowadza:

$ perl test.pl 
1328288600 

który jest: Fri Feb 3 12:03:20 EST 2012

Nie jestem pewien, jak przyzwoity parsowanie jest, ale analizuje swój przykład tylko dobrze :)

+0

Jak mogę uzyskać aktualną datę w tym samym formacie do porównania? localtime (time) daje znacznie dłuższą liczbę. –

+0

@xivix: Nie potrzebujesz 'localtime', po prostu użyj' time': zwraca uniksowy znacznik czasu (sekundy od 1 stycznia 1970 00:00:00 UTC), podobnie jak 'str2time'. –

+0

Na szczęście dla twoich potrzeb, perl używa konwencji Unix mierzącego czas w sekundach od 1 stycznia 1970, więc wynik str2parse powyżej jest już w sekundach, i możesz zrobić matematykę. – theglauber

2

Zakładając, że chcesz użyć Date::Calc, przekonwertuj dwie wartości na "czas" wartościami Date_to_Time, s odejmij wartości, aby uzyskać różnicę w sekundach. Ale aby to zrobić, musisz przekonwertować ciągi znaków na wartości YY MM DD hh mm ss, aby najpierw przejść do Date_to_Time.

6

W duchu TMTOWTDI można wykorzystać rdzeń Time::Piece:

#!/usr/bin/env perl 
use strict; 
use warnings; 
use Time::Piece; 
my $when = "@ARGV" or die "'Mon Day HH:MM:SS' expected\n"; 
my $year = (localtime)[5] + 1900; 
my $t = Time::Piece->strptime($year . q() . $when, "%Y %b %d %H:%M:%S"); 
print "delta seconds = ", time() - $t->strftime("%s"),"\n"; 

$ ./mydelta Lut 3 12:03:20

delta seconds = 14553 

Obecny rok zakłada i pochodzi z twój czas lokalny.

+1

Nie wiem dlaczego, ale '$ t-> epoka' działa, podczas gdy' $ t-> strftime ("% s") 'nie ma – Zaid

+0

@ Zaid Jaka wersja [Time :: Piece] (https: // metacpan. org/changes/distribution/Time-Piece) używasz? Wygląda na to, że 1.20 dodał obsługę 'strftime' dla'% s'. – JRFerguson

+0

$ t-> epoka wydaje się używać niektórych ustawień lokalizacji, których nie jestem świadomy. W moim przypadku 'epoch' zwraca wartość strefy czasowej EDT, podczas gdy ja jestem w czasie JST (Japonia). Jednakże 'strftime ("% s ")' zwraca poprawną wartość w sekundach (JST), co jest zgodne z 'time()'. – lepe

18
#!/usr/bin/perl 

$Start = time(); 
sleep 3; 
$End = time(); 
$Diff = $End - $Start; 

print "Start ".$Start."\n"; 
print "End ".$End."\n"; 
print "Diff ".$Diff."\n"; 

Jest to prosty sposób na znalezienie różnicy czasu w sekundach.

+0

To wcale nie odpowiada na pytanie, które polega na porównywaniu czasów w dwóch zmiennych. – RichVel

+0

To prawda, ale pozwala ... a.) Osoba, która zadała oryginalne pytanie, rozważyła inne podejście, które może być prostsze niż jego pierwotny sposób; b.) Inni ludzie znajdujący tę stronę poprzez wyszukiwanie w Internecie, aby łatwo zmierzyć sekundy. Należę do tego ostatniego i bardzo podoba mi się przykład Sjoerda. Prosty i nie ma zależności. Właśnie tego szukałem. – Keve

Powiązane problemy