Как найти разницу в днях между текущим днем ​​и датой ввода

$a = "Sat Aug 04 23:59:59 GMT 2012"

Как узнать, что $a старше на 100 дней?

Я не могу использовать дополнительные модули Perl, потому что не могу установить их на все хосты.


person joe    schedule 27.09.2011    source источник
comment
Можете ли вы закончить предложение, я не могу использовать дополнительные модули perl, потому что...?   -  person Johnsyweb    schedule 27.09.2011
comment
не могу установить модуль на все хосты.   -  person joe    schedule 27.09.2011
comment
Если вы не можете установить модули CPAN, значит, вы не программируете на Perl. Вы должны сделать решение этой проблемы своим главным приоритетом.   -  person Dave Cross    schedule 27.09.2011
comment
@joe, если вы не можете установить все модули, то вы также не можете установить какой-либо код, который мы вам даем, так что очень жаль, что мы не можем вам помочь. Или, может быть, вы ошибаетесь насчет невозможности установки модулей.   -  person ikegami    schedule 27.09.2011


Ответы (5)


Вы должны использовать DateTime, если он доступен, а если нет, то следует сделать следующее. На самом деле, на этом этапе вы должны создать свою собственную логику дат, но это все еще довольно просто с помощью модуля core POSIX.

use strict;
use warnings;
use POSIX ();

# get a list of month symbols
my @mons = qw/Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec/;

# Create a symbol -> number table
my %num_for 
    = do {
        my $mon = 0;
        map { $_ => $mon++ } @mons;
    };

# Create the alternation of months

# Create line regex
my $time_rex 
    = qr/ (${\join( '|', @mons )}) 
          \s+ 
          0? (\d+) 
          \s+ 
          (\d{2}) : (\d{2}) : (\d{2}) 
          \s+ 
           # I made the tz optional to handle scalar( localtime )
          (?: (\p{alpha}+) \s+ )?
          (\d{4})
        /x
     ;
...

# Convienience function
sub get_time_value {
    # parse date string
    return unless my @fields = ( shift =~ /$time_rex/ );
    # get numerical month
    $fields[0]  = $num_for{ $fields[0] };
    # perl year kludge
    $fields[-1] -= 1900;
    return wantarray ? @fields[ 4, 3, 2, 1, 0, 6, 5 ]
         :             POSIX::mktime( @fields[ 4, 3, 2, 1, 0, 6 ] )
         ;
}

sub days_prior_to_now {
    return unless defined( my $days_prior = shift );
    return time unless $days_prior;

    $days_prior = - $days_prior if $days_prior < 0;
    my $date_string =  scalar( localtime );
    return unless my ( $sec, $min, $hr, $day, $mon, $year, $tz ) 
           = get_time_value( $date_string )
           ;
    return POSIX::mktime( $sec, $min, $hr, $day - $days_prior, $mon, $year );
}

sub is_100_days_before_now {
    my $a_string    = shift;

    croak "Could not parse '$a_string'!" 
        unless my $a_value = get_time_value( $a_string );
    return $a_value < days_prior_to_now( 100 );
}

if ( is_100_days_before_now( $a )) { 
    ...
}
person Axeman    schedule 27.09.2011

Сначала вам нужно проанализировать эту строку в объекте DateTime, используя DateTime::Format:: Builder для создания пользовательского синтаксического анализатора строк. Затем вы можете получить разницу между ними с помощью:

$dt->delta_days( $datetime );

Где $dt — это объект DateTime из синтаксического анализа строки, а $datetime — ваша ссылка (другой объект DateTime).

person Marco De Lellis    schedule 27.09.2011
comment
В качестве альтернативы вы можете использовать Date::Parse для анализа этой строки, а затем from_epoch для создания объекта DateTime. . - person oylenshpeegul; 27.09.2011

Если вы преодолеете свой страх перед модулями, Date::Calc легко справится с этим:

$ perl -MDate::Calc=Delta_Days,Parse_Date,Today -E 'say Delta_Days(Today, Parse_Date(shift))' "Sat Aug 04 23:59:59 GMT 2012"
312
person oylenshpeegul    schedule 27.09.2011

В стандартной установке Perl доступно множество модулей даты и времени, что означает, что не нужно ничего устанавливать. Этот модуль был доступен в той или иной форме, начиная с версии Perl 3.x:

Вот другие в версии 5.8:

Более новые версии Perl включают:

Вы можете использовать команду perldoc, чтобы увидеть, какие модули вы установили:

C:> perldoc -l Time::Piece
C:\Perl\lib\Time\Piece.pm

Unix хранит время в секундах с момента «Эпохи», то есть 1 января 1970 года, и Perl делает то же самое (даже в Windows).

Таким образом, как только вы переведете свою дату во время Perl, вы можете просто вычесть 8 640 000, то есть количество секунд в 100 днях. (100 дней * 24 часа в день * 60 минут в час * 60 секунд в минуту), а затем преобразовать это обратно в строку.

На самом базовом уровне это можно сделать с помощью функции gmtime в Perl и timegm в модуле Local::Time.

Другие модули упрощают преобразование времени из формата в другой и даже выполняют некоторые математические операции. Мне больше всего нравится Time::Piece, который позволяет использовать формат strptime для быстрого преобразования времени из любого формата. это происходит. Затем вы можете использовать функцию-член epoc, чтобы преобразовать время обратно в секунды, вычесть 8 640 000 и снова преобразовать его в строку.

person David W.    schedule 27.09.2011

Если Time::Piece является ядром вашей версии Perl:

use strict;
use warnings;

use Time::Piece;
use Time::Seconds qw(ONE_DAY);

my $t = "Sat Aug 04 23:59:59 GMT 2012";
my $dt = Time::Piece->strptime($t, "%a %b %d %T %Z %Y");

my $day_str = $dt->strftime("%F");
my $day = Time::Piece->strptime($day_str, "%Y-%m-%d") + 100.5*ONE_DAY();

print $day->strftime("%F"),"\n";
person runrig    schedule 27.09.2011