2012-02-03 2 views
10

В программе Perl У меня есть переменная, содержащая дату/время в этом формате:Разница во времени в секундах

Feb 3 12:03:20 

мне нужно, чтобы определить, если эта дата является более х секунд старый (на основе текущего времени), даже если это происходит в полночь (например, Feb 3 23:59:00 с текущим временем = Feb 4 00:00:30).

Информация о perl date/time, которую я нашел, ошеломляет. Рядом, как я могу сказать, мне нужно использовать Date::Calc, но я не нахожу секунды-дельта. Спасибо :)

ответ

3

В perl всегда есть несколько способов сделать что-то. Вот тот, который использует только модуль, который поставляется в стандартной комплектации с Perl:

#! 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"; 

Чтобы сделать это действительно готовый к производству, она нуждается в лучшей управляемости в год (например, то, что происходит, когда дата начала декабря и в конце дата в январе?) и лучшая обработка ошибок (например, что произойдет, если аббревиатура месяца с 3 символами неверно?).

+0

wow ... путь больше, чем я ожидал ... спасибо –

+2

@xivix, это излишне сложно для того, что вы хотите. [Ответ vmpstr] (http://stackoverflow.com/a/9134822/132382) полностью работоспособен. – pilcrow

+0

Все зависит от того, сколько модулей вы можете использовать или будете использовать. См. Ответ @vmpstr, используя Date :: Parse. Если установка этого модуля является приемлемой, перейдите к ней. Вероятно, это улучшает работу с различными форматами данных и возможными ошибками, чем этот короткий фрагмент кода. – theglauber

9

Кажется, что есть удобный Date::Parse. Вот пример:

use Date::Parse; 

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

И вот что она выводит:

$ perl test.pl 
1328288600 

который: Fri Feb 3 12:03:20 EST 2012

Я не уверен, как порядочные синтаксический анализ, но он разбирает свой пример просто fine :)

+0

как бы получить текущую дату в том же формате для сравнения? localtime (time) дает намного большее число. –

+0

@xivix: вам не нужно «localtime», просто используйте 'time': он возвращает отметку времени Unix (секунды с 1 января 1970 года 00:00:00 UTC), так же, как' str2time'. –

+0

К счастью для ваших нужд, perl использует соглашение Unix о измерении времени в секундах с 1 января 1970 года, поэтому выход str2parse выше уже в секундах, и вы можете выполнить математику. – theglauber

2

Предполагая, что вы хотите использовать Date::Calc, преобразуйте два значения в значения «время» с помощью Date_to_Time и s ubtract значения, чтобы получить разницу в секундах. Но для этого вам необходимо преобразовать из строк значения YY MM DD hh mm ss, чтобы перейти к Date_to_Time.

6

В духе TMTOWTDI, вы можете использовать ядро ​​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 февралю 3 12:03:20

delta seconds = 14553 

В текущем году предполагается и взяты из ваше местное время.

+1

Не знаете, почему, но '$ t-> epoch' работает в то время как' $ t-> strftime ("% s") 'is not – Zaid

+0

@Zaid Какая версия [Time :: Piece] (https: // metacpan. org/changes/distribution/Time-Piece) вы используете? Похоже, 1.20 добавила поддержку 'strftime' для'% s'. – JRFerguson

+0

$ t-> epoch, похоже, использует некоторые настройки локализации, о которых я не знаю. В моем случае «epoch» возвращает значение часового пояса EDT, в то время как я нахожусь в JST (время в Японии). Однако 'strftime ("% s ")' возвращает правильное значение в секундах (JST), что согласуется с '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"; 

Это простой способ найти разницу во времени в секундах.

+0

Это вообще не отвечает на вопрос, а именно о сравнении времени в двух переменных. – RichVel

+0

Правда, НО это позволяет ... a.) Человек, который попросил исходный вопрос рассмотреть другой подход, который может быть проще его/ее первоначального пути; b.) Другие люди, которые находят эту страницу через веб-поиск, чтобы легко измерить прошедшие секунды. Я принадлежу к последнему, и мне очень нравится пример Сьорда. Простой и не имеет зависимостей. Только то, что я искал. – Keve