2015-09-25 5 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;' и 'используйте предупреждения 'для своих программ. Они помогут вам обнаружить ошибки раньше. Если вы изучаете Perl из источника, который не показывает ни одного, он устарел. Вам лучше использовать один из вики-страницы Perl здесь, на SO. Теперь вы никогда не используете дату, которую вводит ваш пользователь. И есть некоторые синтаксические ошибки. Пожалуйста, начните с 'use strict' и' use warnings'. – simbabque

+3

... и «устаревшими» мы имеем в виду буквально десятилетия назад. 'использование предупреждений' был введен в 2000 году; 'use strict' был введен в 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] выглядит например, вы пытаетесь получить доступ ко второму элементу (массивы Perl начинаются с нуля) массива с именем localtime. Но то, что вы на самом деле делаете, это создание анонимного массива, содержащего единственное значение 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); вы может сделать (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, который получает время в секундах с 1 января 1970 года, начиная с time(), что также является временем в секундах с 1 января 1970 года. Это дает вам дельта времени, как вы хотите - в секундах. Вы должны разделить его, если хотите разные единицы.

+2

Если вы используете' Time :: Seconds', вы можете написать 'my $ time_between = (localtime - $ date) -> pretty' и получить его красиво отформатированным – Borodin

Смежные вопросы