Как я могу анализировать относительные даты с Perl?

Мне бы хотелось знать, есть ли модуль для анализа "форматированных человеком" дат в Perl. Я имею в виду такие вещи, как "завтра", "вторник", "на следующей неделе", "1 час назад".

Мои исследования с CPAN показывают, что такого модуля нет, так как бы вы могли его создать? Для этого НЛП находится наверху.

Ответ 1

Date::Manip делает именно это.

Вот пример программы:

#!/usr/bin/perl

use strict;
use Date::Manip;

while (<DATA>)
{
  chomp;
  print UnixDate($_, "%Y-%m-%d %H:%M:%S"),  " ($_)\n";
}

__DATA__
today
yesterday
tomorrow
last Tuesday
next Tuesday
1 hour ago
next week

В результате получается следующий результат:

2008-11-17 15:21:04 (today)
2008-11-16 15:21:04 (yesterday)
2008-11-18 15:21:04 (tomorrow)
2008-11-11 00:00:00 (last Tuesday)
2008-11-18 00:00:00 (next Tuesday)
2008-11-17 14:21:04 (1 hour ago)
2008-11-24 00:00:00 (next week)

UnixDate является одной из функций, предоставляемых Date::Manip, первым аргументом является дата/время в любом формате, поддерживаемом модулем, второй аргумент описывает, как форматировать дату/время. Существуют и другие функции, которые просто анализируют эти "человеческие" даты, без их форматирования, для использования в дельта-вычислениях и т.д.

Ответ 2

вам также может быть интересно посмотреть на семейство DateTime::Format, в частности DateTime:: Format:: Natural. после того, как вы проанализировали дату/время в объекте DateTime, вы можете манипулировать и оценивать его по целому ряду разных способов.

здесь пример программы:

use strict;
use warnings;

use DateTime::Format::Natural;

my( $parser ) = DateTime::Format::Natural->new;

while ( <> ) {

    chomp;
    my( $dt ) = $parser->parse_datetime( $_ );

    if ( $parser->success ) {

        print join( ' ', $dt->ymd, $dt->hms ) . "\n";
    }
    else {

        print $parser->error . "\n";
    }
}

выход:

tomorrow  
2008-11-18 21:48:49  
next Tuesday  
2008-11-25 21:48:53  
1 week from now  
2008-11-24 21:48:57  
1 hour ago  
2008-11-17 20:48:59  

TMTOWTDI:)

-Стив

Ответ 3

Лично я всегда использовал Time::ParseDate. Он понимает в значительной степени каждый формат, который я пробовал.

Абсолютные форматы даты

    Dow, dd Mon yy
    Dow, dd Mon yyyy
    Dow, dd Mon
    dd Mon yy
    dd Mon yyyy
    Month day{st,nd,rd,th}, year
    Month day{st,nd,rd,th}
    Mon dd yyyy
    yyyy/mm/dd
    yyyy-mm-dd      (usually the best date specification syntax)
    yyyy/mm
    mm/dd/yy
    mm/dd/yyyy
    mm/yy
    yy/mm      (only if year > 12, or > 31 if UK)
    yy/mm/dd   (only if year > 12 and day < 32, or year > 31 if UK)
    dd/mm/yy   (only if UK, or an invalid mm/dd/yy or yy/mm/dd)
    dd/mm/yyyy (only if UK, or an invalid mm/dd/yyyy)
    dd/mm      (only if UK, or an invalid mm/dd)

Относительные форматы даты:

    count "days"
    count "weeks"
    count "months"
    count "years"
    Dow "after next"
    Dow "before last"
    Dow                     (requires PREFER_PAST or PREFER_FUTURE)
    "next" Dow
    "tomorrow"
    "today"
    "yesterday"
    "last" dow
    "last week"
    "now"
    "now" "+" count units
    "now" "-" count units
    "+" count units         
    "-" count units
    count units "ago"

Абсолютные временные форматы:

    hh:mm:ss[.ddd] 
    hh:mm 
    hh:mm[AP]M
    hh[AP]M
    hhmmss[[AP]M] 
    "noon"
    "midnight"

Относительные временные форматы:

    count "minutes"         (count can be franctional "1.5" or "1 1/2")
    count "seconds"
    count "hours"
    "+" count units
    "+" count
    "-" count units
    "-" count
    count units "ago"

Форматы часовых поясов:

    [+-]dddd
    GMT[+-]d+
    [+-]dddd (TZN)
    TZN

Специальные форматы:

    [ d]d/Mon/yyyy:hh:mm:ss [[+-]dddd]
    yy/mm/dd.hh:mm

Ответ 4

Я предполагаю, что у вас есть контекст. как НЛП могла бы помочь здесь? как дикая догадка, вы можете просто найти ближайшую дату, точную дату (не относительно сегодняшнего дня), и использовать сегодня/tommorow/вчера, чтобы относиться к этому.