2012-02-03 27 views
10

Trong một chương trình Perl Tôi có một biến chứa ngày/giờ ở định dạng này:chênh giờ chỉ trong vài giây

Feb 3 12:03:20 

tôi cần phải xác định xem ngày đó là hơn x giây cũ (dựa trên thời gian hiện tại), ngay cả khi điều này xảy ra vào nửa đêm (ví dụ: Feb 3 23:59:00 với thời gian hiện tại = Feb 4 00:00:30).

Thông tin ngày/giờ perl tôi đã tìm thấy là tâm-boggling. Gần như tôi có thể nói tôi cần sử dụng Date::Calc, nhưng tôi không tìm thấy một giây-delta. Cảm ơn :)

Trả lời

3

Trong perl, luôn có nhiều cách để làm điều gì đó. Dưới đây là một trong đó chỉ sử dụng một mô-đun mà đến tiêu chuẩn với 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"; 

Để làm điều này thực sự sản xuất-sẵn sàng, nó cần xử lý tốt hơn trong năm (ví dụ, những gì sẽ xảy ra khi ngày bắt đầu trong tháng Mười Hai và cuối vào tháng 1?) và xử lý lỗi tốt hơn (ví dụ: điều gì sẽ xảy ra nếu viết tắt 3 tháng của từ bị viết sai chính tả?).

+0

wow ... cách tham gia nhiều hơn tôi mong đợi ... cảm ơn –

+2

@xivix, nó không cần thiết phức tạp cho những gì bạn muốn. [Câu trả lời của vmpstr] (http://stackoverflow.com/a/9134822/132382) là hoàn toàn khả thi ở đây. – pilcrow

+0

Tất cả phụ thuộc vào số lượng mô-đun bạn có thể hoặc sẽ sử dụng. Xem câu trả lời bằng @vmpstr, sử dụng Date :: Parse. Nếu cài đặt mô-đun đó có thể chấp nhận được, hãy thực hiện nó. Nó có khả năng làm một công việc tốt hơn trong việc xử lý các định dạng dữ liệu khác nhau và các lỗi có thể xảy ra so với đoạn mã ngắn này. – theglauber

9

Dường như có sự tiện lợi Date::Parse. Dưới đây là ví dụ:

use Date::Parse; 

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

Và đây là những gì nó ra:

$ perl test.pl 
1328288600 

đó là: Fri Feb 3 12:03:20 EST 2012

Tôi không chắc chắn như thế nào phong nha các phân tích cú pháp, nhưng nó phân tích ví dụ của bạn chỉ fine :)

+0

làm cách nào để có được ngày hiện tại vào cùng một định dạng để so sánh? giờ địa phương (thời gian) cho một số dài hơn nhiều. –

+0

@xivix: Bạn không cần 'localtime', chỉ cần sử dụng' time': nó trả về dấu thời gian Unix (giây kể từ ngày 1 tháng 1 năm 1970 00:00:00 UTC), giống như 'str2time'. –

+0

May mắn thay cho nhu cầu của bạn, perl sử dụng quy ước thời gian đo Unix trong vài giây kể từ ngày 1 tháng 1 năm 1970, vì vậy đầu ra của str2parse ở trên đã có trong vài giây và bạn có thể thực hiện phép toán. – theglauber

2

Giả sử bạn muốn sử dụng Date::Calc, chuyển đổi hai giá trị thành giá trị "thời gian" với Date_to_Time và s ubtract các giá trị để có được sự khác biệt trong vài giây. Nhưng để thực hiện việc này, bạn cần phải chuyển đổi từ các chuỗi thành các giá trị YY MM DD hh mm ss để vượt qua trước tiên là Date_to_Time.

6

Với tinh thần TMTOWTDI, bạn có thể tận dụng lõi 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 Feb 3 12:03:20

delta seconds = 14553 

Các năm nay được giả định và lấy từ giờ địa phương của bạn.

+1

Không chắc chắn tại sao, nhưng '$ t-> epoch' hoạt động trong khi' $ t-> strftime ("% s") 'không – Zaid

+0

@Zaid Phiên bản nào của [Time :: Piece] (https: // metacpan. org/changes/distribution/Time-Piece) bạn đang sử dụng? Có vẻ như 1,20 đã thêm 'strftime' support cho'% s'. – JRFerguson

+0

$ t-> epoch dường như sử dụng một số cài đặt bản địa hóa mà tôi không biết. Trong trường hợp của tôi, 'epoch' đang trả về giá trị múi giờ EDT, trong khi tôi thực sự đang ở thời gian JST (Nhật Bản). Tuy nhiên, 'strftime ("% s ")' trả về giá trị đúng trong vài giây (JST), nhất quán với '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"; 

Đây là cách đơn giản để tìm sự khác biệt về thời gian tính bằng giây.

+0

Điều này không trả lời được câu hỏi nào cả, đó là về việc so sánh thời gian trong hai biến. – RichVel

+0

Đúng, NHƯNG cho phép ... a.) Người đã hỏi câu hỏi ban đầu để xem xét một cách tiếp cận khác, có thể đơn giản hơn cách ban đầu của anh ấy; b.) Những người khác tìm thấy trang này thông qua tìm kiếm trên web để dễ dàng đo giây trôi qua. Tôi thuộc về sau, và tôi rất giống ví dụ của Sjoerd. Đơn giản và không có phụ thuộc. Chỉ cần những gì tôi đang tìm kiếm. – Keve

Các vấn đề liên quan