Alt-Date-Extract-SHARYANTO

 view release on metacpan or  search on metacpan

lib/Date/Extract.pm  view on Meta::CPAN

package Date::Extract;
use strict;
use warnings;
use DateTime::Format::Natural;
use List::Util 'reduce';
use parent 'Class::Data::Inheritable';

our $VERSION = '0.05.01'; # VERSION
our $DATE = '2014-06-09'; # DATE

__PACKAGE__->mk_classdata($_) for qw/scalar_downgrade handlers regex/;

sub _croak {
    require Carp;
    Carp::croak @_;
}

sub new {
    my $class = shift;
    my %args = (
        format => 'DateTime',
        returns => 'first',
        prefers => 'nearest',
        time_zone => 'floating',
        @_,
    );

    if ($args{format} ne 'DateTime'
     && $args{format} ne 'verbatim'
     && $args{format} ne 'epoch'
     && $args{format} ne 'combined') {
        _croak "Invalid `format` passed to constructor: expected `DateTime', `verbatim', `epoch', `combined'.";
    }

    if ($args{returns} ne 'first'
     && $args{returns} ne 'last'
     && $args{returns} ne 'earliest'
     && $args{returns} ne 'latest'
     && $args{returns} ne 'all'
     && $args{returns} ne 'all_cron') {
        _croak "Invalid `returns` passed to constructor: expected `first', `last', `earliest', `latest', `all', or `all_cron'.";
    }

    if ($args{prefers} ne 'nearest'
     && $args{prefers} ne 'past'
     && $args{prefers} ne 'future') {
        _croak "Invalid `prefers` passed to constructor: expected `nearest', `past', or `future'.";
    }

    my $self = bless \%args, ref($class) || $class;

    return $self;
}

# This method will combine the arguments of parser->new and extract. Modify the
# "to" hash directly.

sub _combine_args {
    shift;

    my $from = shift;
    my $to = shift;

    $to->{format}    ||= $from->{format};
    $to->{prefers}   ||= $from->{prefers};
    $to->{returns}   ||= $from->{returns};
    $to->{time_zone} ||= $from->{time_zone};
}

sub extract {
    my $self = shift;
    my $text = shift;
    my %args = @_;

    # using extract as a class method
    $self = $self->new
        if !ref($self);

    # combine the arguments of parser->new and this
    $self->_combine_args($self, \%args);

    # when in scalar context, downgrade
    $args{returns} = $self->_downgrade($args{returns})
        unless wantarray;

    # do the work
    my @ret = $self->_extract($text, %args);

    # munge the output to match the desired return type
    return $self->_handle($args{returns}, @ret);
}

# build the giant regex used for parsing. it has to be a single regex, so that
# the order of matches is correct.
sub _build_regex {
    my $self = shift;

    my $relative          = '(?:today|tomorrow|yesterday)';

    my $long_weekday      = '(?:Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday)';
    my $short_weekday     = '(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun)';
    my $weekday           = "(?:$long_weekday|$short_weekday)";

    my $relative_weekday  = "(?:(?:next|previous|last)\\s*$weekday)";

    my $long_month        = '(?:January|February|March|April|May|June|July|August|September|October|November|December)';
    my $short_month       = '(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)';
    my $month             = "(?:$long_month|$short_month)";

    # 1 - 31



( run in 1.816 second using v1.01-cache-2.11-cpan-39bf76dae61 )