2015-09-25 101 views
1

我试图计算和显示,以分钟为单位,输入的日期和当前时间之间的差异。我有:查找两个日期之间的时间在Perl

print "Enter a date YYYY MM DD. Remember perl's months go from 0-11.\n"; 
while (@dateEnt < 1) { 
    my $dateEntered = <STDIN>; 
    chomp $dateEntered; 
    push @dateEnt, $dateEntered; 

    (@datedata) = split(/\s+/, $dateEntered); 
    $year = $datedata[0]; 
    $month = $datedata[1]; 
    $day = $datedata[2]; 
} 

$time   = time; 
$readabletime = localtime($time); 

use Time::Local; 
$timeB = localtime [1]; 
$timeBetween = $readabletime[1] - $timeB; 
print "The time between the dates is $timeBetween\n"; 

当我执行此操作时,我没有得到答案。任何帮助?

+4

欢迎使用Stack Overflow和_perl_标记。请确保您总是在程序中添加'use strict;'和'warnings'。它们可以帮助您尽早发现错误。如果你从一个既不显示也不显示的源代码学习Perl,它已经过时了。您最好使用SO标签中的Perl标签wiki。现在,你永远不会使用你的用户输入的日期。还有一些语法错误。请以'use strict'和'使用警告'开始。 – simbabque

+3

...和“过时”我们的意思是字面上几十年的老。 2000年推出“使用警告”; '使用严格'于1994年推出。 – melpomene

回答

3

让我们来看看这最后一块

use Time::Local; 
$timeB = localtime[1]; 
$timeBetween = $readabletime[1] - $timeB; 
print "The time between the dates is $timeBetween\n"; 

use声明是在程序的顶部通常放,因为它在编译时实际执行,但它的罚款的任何地方真的

localtime[1]外观就像您正在尝试访问名为localtime的数组的第二个元素(Perl数组从零开始)。但是你实际上做的是创建一个匿名数组,其中包含单值1并将其引用传递给localtime。如果您尝试使用print[1],您会看到类似ARRAY(0x22c4000)的东西。所以localtime试图内存地址转换成一个日期和时间

$readabletime[1]试图访问数组@readabletime的第二个元素,它不存在,因此将评估为undef

你最终想减去有点像"Thu Mar 4 18:50:24 1971"undef这是没有意义的。我想你应该得到一个致命的错误类似

Argument "Thu Mar 4 18:50:24 1971" isn't numeric in subtraction 
1

你可以试试这个

use strict; 
use warnings; 
use DateTime; 

my $from_date = DateTime->new(
         year => 2014, 
         month => 9, 
         day => 24, 
         hour => 9, 
         minute => 13, 
         second => 8, 
         time_zone => 'local', 
        ); 
print "$from_date\n"; 
my $current_date = DateTime->now(time_zone => 'local')->set_time_zone('floating'); 
print "$current_date\n"; 
my $time_diff = $current_date - $from_date; 
print 'year = ', $time_diff->years, "\n"; 
print 'month = ', $time_diff->months, "\n"; 
print 'days = ', $time_diff->days, "\n"; 
print 'hours = ', $time_diff->hours, "\n"; 
print 'minutes = ', $time_diff->minutes, "\n"; 
print 'secondss = ', $time_diff->seconds, "\n"; 

结果:

2014-09-24T09:13:08 
2015-09-25T21:31:37 
year = 1 
month = 0 
days = 1 
hours = 12 
minutes = 18 
secondss = 29 
3

use strict;use warnings;会告诉你很多的问题。

  • while循环是多余的,因为你push没有任何验证。所以它会总是在第二次迭代是正确的。
  • 这使得@dateEnt冗余。
  • 在标量上下文
  • localtime给出了一个字符串。你不能用字符串做数学。 (偶尔你可以作弊,因为perl可以将其转换为数字,但不适用于日期字符串)。
  • use通常是在一个程序的顶部,因为它是在一个数组背景下“完成”无论
  • localtime的第一件事就是返回值的数组。 ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); you can do (localtime)[1]它给你$min。但是,无论如何,这并不太有意义。
  • $readabletime[1]指称为@readabletime的数组的第二个元素。这不存在。

所以来完成你以后 - 我会建议使用Time::Piece(Perl核心模块)是这样的:

#!/usr/bin/perl 
use strict; 
use warnings; 
use Time::Piece 

my $date; 
while (not $date) { 
    print "Enter a date YYYY MM DD\n"; 
    my $dateEntered = <STDIN>; 
    chomp $dateEntered; 
    $date = Time::Piece->strptime($dateEntered, "%Y %m %d"); 
} 
print "Understood: $date\n"; 
my $timebetween_s = (time() - $date->epoch); 
print $timebetween_s, "s between then and now\n"; 

注意 - 它使用strptime所输入的日期转换为Time::Piece对象(你可以只需print,如果你想得到一个字符串日期,但你也可以做其他转换)。 strptime支持许多不同的格式。

但你只是减去$date->epoch - 它得到的时间(秒)自1970年1月1日,从time()这也是自1月1日1970年以秒为单位的时间这让你像你想有一个时间差 - 在几秒钟。如果你想要不同的单位,你需要分割它。

+2

如果您同时使用'Time :: Seconds',则可以编写'my $ time_between =(localtime - $ date) - > pretty'并将其格式化得很好 – Borodin

相关问题