Blame lib/DateTime/Format/Builder.pm

Packit 9002b2
package DateTime::Format::Builder;
Packit 9002b2
{
Packit 9002b2
  $DateTime::Format::Builder::VERSION = '0.81';
Packit 9002b2
}
Packit 9002b2
Packit 9002b2
use strict;
Packit 9002b2
use warnings;
Packit 9002b2
Packit 9002b2
use 5.005;
Packit 9002b2
use Carp;
Packit 9002b2
use DateTime 1.00;
Packit 9002b2
use Params::Validate 0.72 qw(
Packit 9002b2
    validate SCALAR ARRAYREF HASHREF SCALARREF CODEREF GLOB GLOBREF UNDEF
Packit 9002b2
);
Packit 9002b2
use vars qw( %dispatch_data );
Packit 9002b2
Packit 9002b2
my $parser = 'DateTime::Format::Builder::Parser';
Packit 9002b2
Packit 9002b2
sub verbose {
Packit 9002b2
    warn "Use of verbose() deprecated for the interim.";
Packit 9002b2
    1;
Packit 9002b2
}
Packit 9002b2
Packit 9002b2
sub import {
Packit 9002b2
    my $class = shift;
Packit 9002b2
    $class->create_class( @_, class => (caller)[0] ) if @_;
Packit 9002b2
}
Packit 9002b2
Packit 9002b2
sub create_class {
Packit 9002b2
    my $class = shift;
Packit 9002b2
    my %args  = validate(
Packit 9002b2
        @_,
Packit 9002b2
        {
Packit 9002b2
            class   => { type => SCALAR, default  => (caller)[0] },
Packit 9002b2
            version => { type => SCALAR, optional => 1 },
Packit 9002b2
            verbose => { type => SCALAR | GLOBREF | GLOB, optional => 1 },
Packit 9002b2
            parsers => { type => HASHREF },
Packit 9002b2
            groups  => { type => HASHREF,                 optional => 1 },
Packit 9002b2
            constructor =>
Packit 9002b2
                { type => UNDEF | SCALAR | CODEREF, optional => 1 },
Packit 9002b2
        }
Packit 9002b2
    );
Packit 9002b2
Packit 9002b2
    verbose( $args{verbose} ) if exists $args{verbose};
Packit 9002b2
Packit 9002b2
    my $target = $args{class};    # where we're writing our methods and such.
Packit 9002b2
Packit 9002b2
    # Create own lovely new package
Packit 9002b2
    {
Packit 9002b2
        no strict 'refs';
Packit 9002b2
Packit 9002b2
        ${"${target}::VERSION"} = $args{version} if exists $args{version};
Packit 9002b2
Packit 9002b2
        $class->create_constructor(
Packit 9002b2
            $target, exists $args{constructor},
Packit 9002b2
            $args{constructor}
Packit 9002b2
        );
Packit 9002b2
Packit 9002b2
        # Turn groups of parser specs in to groups of parsers
Packit 9002b2
        {
Packit 9002b2
            my $specs = $args{groups};
Packit 9002b2
            my %groups;
Packit 9002b2
Packit 9002b2
            for my $label ( keys %$specs ) {
Packit 9002b2
                my $parsers = $specs->{$label};
Packit 9002b2
                my $code    = $class->create_parser($parsers);
Packit 9002b2
                $groups{$label} = $code;
Packit 9002b2
            }
Packit 9002b2
Packit 9002b2
            $dispatch_data{$target} = \%groups;
Packit 9002b2
        }
Packit 9002b2
Packit 9002b2
        # Write all our parser methods, creating parsers as we go.
Packit 9002b2
        while ( my ( $method, $parsers ) = each %{ $args{parsers} } ) {
Packit 9002b2
            my $globname = $target . "::$method";
Packit 9002b2
            croak "Will not override a preexisting method $method()"
Packit 9002b2
                if defined &{$globname};
Packit 9002b2
            *$globname = $class->create_end_parser($parsers);
Packit 9002b2
        }
Packit 9002b2
    }
Packit 9002b2
Packit 9002b2
}
Packit 9002b2
Packit 9002b2
sub create_constructor {
Packit 9002b2
    my $class = shift;
Packit 9002b2
    my ( $target, $intended, $value ) = @_;
Packit 9002b2
Packit 9002b2
    my $new = $target . "::new";
Packit 9002b2
    $value = 1 unless $intended;
Packit 9002b2
Packit 9002b2
    return unless $value;
Packit 9002b2
    return if not $intended and defined &$new;
Packit 9002b2
    croak "Will not override a preexisting constructor new()"
Packit 9002b2
        if defined &$new;
Packit 9002b2
Packit 9002b2
    no strict 'refs';
Packit 9002b2
Packit 9002b2
    return *$new = $value if ref $value eq 'CODE';
Packit 9002b2
    return *$new = sub {
Packit 9002b2
        my $class = shift;
Packit 9002b2
        croak "${class}->new takes no parameters." if @_;
Packit 9002b2
Packit 9002b2
        my $self = bless {}, ref($class) || $class;
Packit 9002b2
Packit 9002b2
        # If called on an object, clone, but we've nothing to
Packit 9002b2
        # clone
Packit 9002b2
Packit 9002b2
        $self;
Packit 9002b2
    };
Packit 9002b2
}
Packit 9002b2
Packit 9002b2
sub create_parser {
Packit 9002b2
    my $class = shift;
Packit 9002b2
    my @common = ( maker => $class );
Packit 9002b2
    if ( @_ == 1 ) {
Packit 9002b2
        my $parsers = shift;
Packit 9002b2
        my @parsers = (
Packit 9002b2
            ( ref $parsers eq 'HASH' )
Packit 9002b2
            ? %$parsers
Packit 9002b2
            : ( ( ref $parsers eq 'ARRAY' ) ? @$parsers : $parsers )
Packit 9002b2
        );
Packit 9002b2
        $parser->create_parser( \@common, @parsers );
Packit 9002b2
    }
Packit 9002b2
    else {
Packit 9002b2
        $parser->create_parser( \@common, @_ );
Packit 9002b2
    }
Packit 9002b2
}
Packit 9002b2
Packit 9002b2
Packit 9002b2
sub create_end_parser {
Packit 9002b2
    my ( $class, $parsers ) = @_;
Packit 9002b2
    $class->create_method( $class->create_parser($parsers) );
Packit 9002b2
}
Packit 9002b2
Packit 9002b2
sub create_method {
Packit 9002b2
    my ( $class, $parser ) = @_;
Packit 9002b2
    return sub {
Packit 9002b2
        my $self = shift;
Packit 9002b2
        $parser->parse( $self, @_ );
Packit 9002b2
        }
Packit 9002b2
}
Packit 9002b2
Packit 9002b2
sub on_fail {
Packit 9002b2
    my ( $class, $input ) = @_;
Packit 9002b2
Packit 9002b2
    my $pkg;
Packit 9002b2
    my $i = 0;
Packit 9002b2
    while ( ($pkg) = caller( $i++ ) ) {
Packit 9002b2
        last
Packit 9002b2
            if ( !UNIVERSAL::isa( $pkg, 'DateTime::Format::Builder' )
Packit 9002b2
            && !UNIVERSAL::isa( $pkg, 'DateTime::Format::Builder::Parser' ) );
Packit 9002b2
    }
Packit 9002b2
    local $Carp::CarpLevel = $i;
Packit 9002b2
    croak "Invalid date format: $input";
Packit 9002b2
}
Packit 9002b2
Packit 9002b2
sub new {
Packit 9002b2
    my $class = shift;
Packit 9002b2
    croak "Constructor 'new' takes no parameters" if @_;
Packit 9002b2
    my $self = bless {
Packit 9002b2
        parser => sub { croak "No parser set." }
Packit 9002b2
        },
Packit 9002b2
        ref($class) || $class;
Packit 9002b2
    if ( ref $class ) {
Packit 9002b2
Packit 9002b2
        # If called on an object, clone
Packit 9002b2
        $self->set_parser( $class->get_parser );
Packit 9002b2
Packit 9002b2
        # and that's it. we don't store that much info per object
Packit 9002b2
    }
Packit 9002b2
    return $self;
Packit 9002b2
}
Packit 9002b2
Packit 9002b2
sub parser {
Packit 9002b2
    my $class  = shift;
Packit 9002b2
    my $parser = $class->create_end_parser( \@_ );
Packit 9002b2
Packit 9002b2
    # Do we need to instantiate a new object for return,
Packit 9002b2
    # or are we modifying an existing object?
Packit 9002b2
    my $self;
Packit 9002b2
    $self = ref $class ? $class : $class->new();
Packit 9002b2
Packit 9002b2
    $self->set_parser($parser);
Packit 9002b2
Packit 9002b2
    $self;
Packit 9002b2
}
Packit 9002b2
Packit 9002b2
sub clone {
Packit 9002b2
    my $self = shift;
Packit 9002b2
    croak "Calling object method as class method!" unless ref $self;
Packit 9002b2
    return $self->new();
Packit 9002b2
}
Packit 9002b2
Packit 9002b2
sub set_parser {
Packit 9002b2
    my ( $self, $parser ) = @_;
Packit 9002b2
    croak "set_parser given something other than a coderef"
Packit 9002b2
        unless $parser
Packit 9002b2
        and ref $parser eq 'CODE';
Packit 9002b2
    $self->{parser} = $parser;
Packit 9002b2
    $self;
Packit 9002b2
}
Packit 9002b2
Packit 9002b2
sub get_parser {
Packit 9002b2
    my ($self) = @_;
Packit 9002b2
    return $self->{parser};
Packit 9002b2
}
Packit 9002b2
Packit 9002b2
sub parse_datetime {
Packit 9002b2
    my $self = shift;
Packit 9002b2
    croak "parse_datetime is an object method, not a class method."
Packit 9002b2
        unless ref $self and $self->isa(__PACKAGE__);
Packit 9002b2
    croak "No date specified." unless @_;
Packit 9002b2
    return $self->{parser}->( $self, @_ );
Packit 9002b2
}
Packit 9002b2
Packit 9002b2
sub format_datetime {
Packit 9002b2
    croak __PACKAGE__ . "::format_datetime not implemented.";
Packit 9002b2
}
Packit 9002b2
Packit 9002b2
require DateTime::Format::Builder::Parser;
Packit 9002b2
Packit 9002b2
1;
Packit 9002b2
Packit 9002b2
# ABSTRACT: Create DateTime parser classes and objects.
Packit 9002b2
Packit 9002b2
__END__
Packit 9002b2
Packit 9002b2
=pod
Packit 9002b2
Packit 9002b2
=head1 NAME
Packit 9002b2
Packit 9002b2
DateTime::Format::Builder - Create DateTime parser classes and objects.
Packit 9002b2
Packit 9002b2
=head1 VERSION
Packit 9002b2
Packit 9002b2
version 0.81
Packit 9002b2
Packit 9002b2
=head1 SYNOPSIS
Packit 9002b2
Packit 9002b2
    package DateTime::Format::Brief;
Packit 9002b2
Packit 9002b2
    use DateTime::Format::Builder
Packit 9002b2
    (
Packit 9002b2
        parsers => {
Packit 9002b2
            parse_datetime => [
Packit 9002b2
            {
Packit 9002b2
                regex => qr/^(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/,
Packit 9002b2
                params => [qw( year month day hour minute second )],
Packit 9002b2
            },
Packit 9002b2
            {
Packit 9002b2
                regex => qr/^(\d{4})(\d\d)(\d\d)$/,
Packit 9002b2
                params => [qw( year month day )],
Packit 9002b2
            },
Packit 9002b2
            ],
Packit 9002b2
        }
Packit 9002b2
    );
Packit 9002b2
Packit 9002b2
=head1 DESCRIPTION
Packit 9002b2
Packit 9002b2
DateTime::Format::Builder creates DateTime parsers.
Packit 9002b2
Many string formats of dates and times are simple and just
Packit 9002b2
require a basic regular expression to extract the relevant
Packit 9002b2
information. Builder provides a simple way to do this
Packit 9002b2
without writing reams of structural code.
Packit 9002b2
Packit 9002b2
Builder provides a number of methods, most of which you'll
Packit 9002b2
never need, or at least rarely need. They're provided more
Packit 9002b2
for exposing of the module's innards to any subclasses, or
Packit 9002b2
for when you need to do something slightly beyond what I
Packit 9002b2
expected.
Packit 9002b2
Packit 9002b2
This creates the end methods. Coderefs die on bad parses,
Packit 9002b2
return C<DateTime> objects on good parse.
Packit 9002b2
Packit 9002b2
=head1 TUTORIAL
Packit 9002b2
Packit 9002b2
See L<DateTime::Format::Builder::Tutorial>.
Packit 9002b2
Packit 9002b2
=head1 ERROR HANDLING AND BAD PARSES
Packit 9002b2
Packit 9002b2
Often, I will speak of C<undef> being returned, however
Packit 9002b2
that's not strictly true.
Packit 9002b2
Packit 9002b2
When a simple single specification is given for a method,
Packit 9002b2
the method isn't given a single parser directly. It's given
Packit 9002b2
a wrapper that will call C<on_fail()> if the single parser
Packit 9002b2
returns C<undef>. The single parser must return C<undef> so
Packit 9002b2
that a multiple parser can work nicely and actual errors can
Packit 9002b2
be thrown from any of the callbacks.
Packit 9002b2
Packit 9002b2
Similarly, any multiple parsers will only call C<on_fail()>
Packit 9002b2
right at the end when it's tried all it could.
Packit 9002b2
Packit 9002b2
C<on_fail()> (see L<later|/on_fail>) is defined, by default,
Packit 9002b2
to throw an error.
Packit 9002b2
Packit 9002b2
Multiple parser specifications can also specify C<on_fail>
Packit 9002b2
with a coderef as an argument in the options block. This
Packit 9002b2
will take precedence over the inheritable and over-ridable
Packit 9002b2
method.
Packit 9002b2
Packit 9002b2
That said, don't throw real errors from callbacks in
Packit 9002b2
multiple parser specifications unless you really want
Packit 9002b2
parsing to stop right there and not try any other parsers.
Packit 9002b2
Packit 9002b2
In summary: calling a B<method> will result in either a
Packit 9002b2
C<DateTime> object being returned or an error being thrown
Packit 9002b2
(unless you've overridden C<on_fail()> or
Packit 9002b2
C<create_method()>, or you've specified a C<on_fail> key to
Packit 9002b2
a multiple parser specification).
Packit 9002b2
Packit 9002b2
Individual B<parsers> (be they multiple parsers or single
Packit 9002b2
parsers) will return either the C<DateTime> object or
Packit 9002b2
C<undef>.
Packit 9002b2
Packit 9002b2
=head1 SINGLE SPECIFICATIONS
Packit 9002b2
Packit 9002b2
A single specification is a hash ref of instructions
Packit 9002b2
on how to create a parser.
Packit 9002b2
Packit 9002b2
The precise set of keys and values varies according to parser
Packit 9002b2
type. There are some common ones though:
Packit 9002b2
Packit 9002b2
=over 4
Packit 9002b2
Packit 9002b2
=item *
Packit 9002b2
Packit 9002b2
B<length> is an optional parameter that can be used to
Packit 9002b2
specify that this particular I<regex> is only applicable to
Packit 9002b2
strings of a certain fixed length. This can be used to make
Packit 9002b2
parsers more efficient. It's strongly recommended that any
Packit 9002b2
parser that can use this parameter does.
Packit 9002b2
Packit 9002b2
You may happily specify the same length twice. The parsers
Packit 9002b2
will be tried in order of specification.
Packit 9002b2
Packit 9002b2
You can also specify multiple lengths by giving it an
Packit 9002b2
arrayref of numbers rather than just a single scalar.
Packit 9002b2
If doing so, please keep the number of lengths to a minimum.
Packit 9002b2
Packit 9002b2
If any specifications without I<length>s are given and the
Packit 9002b2
particular I<length> parser fails, then the non-I<length>
Packit 9002b2
parsers are tried.
Packit 9002b2
Packit 9002b2
This parameter is ignored unless the specification is part
Packit 9002b2
of a multiple parser specification.
Packit 9002b2
Packit 9002b2
=item *
Packit 9002b2
Packit 9002b2
B<label> provides a name for the specification and is passed
Packit 9002b2
to some of the callbacks about to mentioned.
Packit 9002b2
Packit 9002b2
=item *
Packit 9002b2
Packit 9002b2
B<on_match> and B<on_fail> are callbacks. Both routines will
Packit 9002b2
be called with parameters of:
Packit 9002b2
Packit 9002b2
=over 4
Packit 9002b2
Packit 9002b2
=item *
Packit 9002b2
Packit 9002b2
B<input>, being the input to the parser (after any
Packit 9002b2
preprocessing callbacks).
Packit 9002b2
Packit 9002b2
=item *
Packit 9002b2
Packit 9002b2
B<label>, being the label of the parser, if there is one.
Packit 9002b2
Packit 9002b2
=item *
Packit 9002b2
Packit 9002b2
B<self>, being the object on which the method has been
Packit 9002b2
invoked (which may just be a class name). Naturally, you
Packit 9002b2
can then invoke your own methods on it do get information
Packit 9002b2
you want.
Packit 9002b2
Packit 9002b2
=item *
Packit 9002b2
Packit 9002b2
B<args>, being an arrayref of any passed arguments, if any.
Packit 9002b2
If there were no arguments, then this parameter is not given.
Packit 9002b2
Packit 9002b2
=back
Packit 9002b2
Packit 9002b2
These routines will be called depending on whether the
Packit 9002b2
B<regex> match succeeded or failed.
Packit 9002b2
Packit 9002b2
=item *
Packit 9002b2
Packit 9002b2
B<preprocess> is a callback provided for cleaning up input
Packit 9002b2
prior to parsing. It's given a hash as arguments with the
Packit 9002b2
following keys:
Packit 9002b2
Packit 9002b2
=over 4
Packit 9002b2
Packit 9002b2
=item *
Packit 9002b2
Packit 9002b2
B<input> being the datetime string the parser was given (if
Packit 9002b2
using multiple specifications and an overall I<preprocess>
Packit 9002b2
then this is the date after it's been through that
Packit 9002b2
preprocessor).
Packit 9002b2
Packit 9002b2
=item *
Packit 9002b2
Packit 9002b2
B<parsed> being the state of parsing so far. Usually empty
Packit 9002b2
at this point unless an overall I<preprocess> was given.
Packit 9002b2
Items may be placed in it and will be given to any
Packit 9002b2
B<postprocess>or and C<< DateTime->new >> (unless the
Packit 9002b2
postprocessor deletes it).
Packit 9002b2
Packit 9002b2
=item *
Packit 9002b2
Packit 9002b2
B<self>, B<args>, B<label> as per I<on_match> and I<on_fail>.
Packit 9002b2
Packit 9002b2
=back
Packit 9002b2
Packit 9002b2
The return value from the routine is what is given to the
Packit 9002b2
I<regex>. Note that this is last code stop before the match.
Packit 9002b2
Packit 9002b2
B<Note>: mixing I<length> and a I<preprocess> that modifies
Packit 9002b2
the length of the input string is probably not what you
Packit 9002b2
meant to do. You probably meant to use the
Packit 9002b2
I<multiple parser> variant of I<preprocess> which is done
Packit 9002b2
B<before> any length calculations. This C<single parser> variant
Packit 9002b2
of I<preprocess> is performed B<after> any length
Packit 9002b2
calculations.
Packit 9002b2
Packit 9002b2
=item *
Packit 9002b2
Packit 9002b2
B<postprocess> is the last code stop before
Packit 9002b2
C<< DateTime->new() >> is called. It's given the same
Packit 9002b2
arguments as I<preprocess>. This allows it to modify the
Packit 9002b2
parsed parameters after the parse and before the creation
Packit 9002b2
of the object. For example, you might use:
Packit 9002b2
Packit 9002b2
    {
Packit 9002b2
        regex  => qr/^(\d\d) (\d\d) (\d\d)$/,
Packit 9002b2
	params => [qw( year  month  day   )],
Packit 9002b2
	postprocess => \&_fix_year,
Packit 9002b2
    }
Packit 9002b2
Packit 9002b2
where C<_fix_year> is defined as:
Packit 9002b2
Packit 9002b2
    sub _fix_year
Packit 9002b2
    {
Packit 9002b2
        my %args = @_;
Packit 9002b2
	my ($date, $p) = @args{qw( input parsed )};
Packit 9002b2
	$p->{year} += $p->{year} > 69 ? 1900 : 2000;
Packit 9002b2
	return 1;
Packit 9002b2
    }
Packit 9002b2
Packit 9002b2
This will cause the two digit years to be corrected
Packit 9002b2
according to the cut off. If the year was '69' or lower,
Packit 9002b2
then it is made into 2069 (or 2045, or whatever the year was
Packit 9002b2
parsed as). Otherwise it is assumed to be 19xx. The
Packit 9002b2
L<DateTime::Format::Mail> module uses code similar to this
Packit 9002b2
(only it allows the cut off to be configured and it doesn't
Packit 9002b2
use Builder).
Packit 9002b2
Packit 9002b2
B<Note>: It is B<very important> to return an explicit value
Packit 9002b2
from the I<postprocess> callback. If the return value is
Packit 9002b2
false then the parse is taken to have failed. If the return
Packit 9002b2
value is true, then the parse is taken to have succeeded and
Packit 9002b2
C<< DateTime->new() >> is called.
Packit 9002b2
Packit 9002b2
=back
Packit 9002b2
Packit 9002b2
See the documentation for the individual parsers for their
Packit 9002b2
valid keys.
Packit 9002b2
Packit 9002b2
Parsers at the time of writing are:
Packit 9002b2
Packit 9002b2
=over 4
Packit 9002b2
Packit 9002b2
=item *
Packit 9002b2
Packit 9002b2
L<DateTime::Format::Builder::Parser::Regex> - provides regular
Packit 9002b2
expression based parsing.
Packit 9002b2
Packit 9002b2
=item *
Packit 9002b2
Packit 9002b2
L<DateTime::Format::Builder::Parser::Strptime> - provides strptime
Packit 9002b2
based parsing.
Packit 9002b2
Packit 9002b2
=back
Packit 9002b2
Packit 9002b2
=head2 Subroutines / coderefs as specifications.
Packit 9002b2
Packit 9002b2
A single parser specification can be a coderef. This was
Packit 9002b2
added mostly because it could be and because I knew someone,
Packit 9002b2
somewhere, would want to use it.
Packit 9002b2
Packit 9002b2
If the specification is a reference to a piece of code, be
Packit 9002b2
it a subroutine, anonymous, or whatever, then it's passed
Packit 9002b2
more or less straight through. The code should return
Packit 9002b2
C<undef> in event of failure (or any false value,
Packit 9002b2
but C<undef> is strongly preferred), or a true value in the
Packit 9002b2
event of success (ideally a C<DateTime> object or some
Packit 9002b2
object that has the same interface).
Packit 9002b2
Packit 9002b2
This all said, I generally wouldn't recommend using this
Packit 9002b2
feature unless you have to.
Packit 9002b2
Packit 9002b2
=head2 Callbacks
Packit 9002b2
Packit 9002b2
I mention a number of callbacks in this document.
Packit 9002b2
Packit 9002b2
Any time you see a callback being mentioned, you can,
Packit 9002b2
if you like, substitute an arrayref of coderefs rather
Packit 9002b2
than having the straight coderef.
Packit 9002b2
Packit 9002b2
=head1 MULTIPLE SPECIFICATIONS
Packit 9002b2
Packit 9002b2
These are very easily described as an array of single
Packit 9002b2
specifications.
Packit 9002b2
Packit 9002b2
Note that if the first element of the array is an arrayref,
Packit 9002b2
then you're specifying options.
Packit 9002b2
Packit 9002b2
=over 4
Packit 9002b2
Packit 9002b2
=item *
Packit 9002b2
Packit 9002b2
B<preprocess> lets you specify a preprocessor that is called
Packit 9002b2
before any of the parsers are tried. This lets you do things
Packit 9002b2
like strip off timezones or any unnecessary data. The most
Packit 9002b2
common use people have for it at present is to get the input
Packit 9002b2
date to a particular length so that the I<length> is usable
Packit 9002b2
(L<DateTime::Format::ICal> would use it to strip off the
Packit 9002b2
variable length timezone).
Packit 9002b2
Packit 9002b2
Arguments are as for the I<single parser> I<preprocess>
Packit 9002b2
variant with the exception that I<label> is never given.
Packit 9002b2
Packit 9002b2
=item *
Packit 9002b2
Packit 9002b2
B<on_fail> should be a reference to a subroutine that is
Packit 9002b2
called if the parser fails. If this is not provided, the
Packit 9002b2
default action is to call
Packit 9002b2
C<DateTime::Format::Builder::on_fail>, or the C<on_fail>
Packit 9002b2
method of the subclass of DTFB that was used to create the
Packit 9002b2
parser.
Packit 9002b2
Packit 9002b2
=back
Packit 9002b2
Packit 9002b2
=head1 EXECUTION FLOW
Packit 9002b2
Packit 9002b2
Builder allows you to plug in a fair few callbacks, which
Packit 9002b2
can make following how a parse failed (or succeeded
Packit 9002b2
unexpectedly) somewhat tricky.
Packit 9002b2
Packit 9002b2
=head2 For Single Specifications
Packit 9002b2
Packit 9002b2
A single specification will do the following:
Packit 9002b2
Packit 9002b2
User calls parser:
Packit 9002b2
Packit 9002b2
       my $dt = $class->parse_datetime( $string );
Packit 9002b2
Packit 9002b2
=over 4
Packit 9002b2
Packit 9002b2
=item 1
Packit 9002b2
Packit 9002b2
I<preprocess> is called. It's given C<$string> and a
Packit 9002b2
reference to the parsing workspace hash, which we'll call
Packit 9002b2
C<$p>. At this point, C<$p> is empty. The return value is
Packit 9002b2
used as C<$date> for the rest of this single parser.
Packit 9002b2
Anything put in C<$p> is also used for the rest of this
Packit 9002b2
single parser.
Packit 9002b2
Packit 9002b2
=item 2
Packit 9002b2
Packit 9002b2
I<regex> is applied.
Packit 9002b2
Packit 9002b2
=item 3
Packit 9002b2
Packit 9002b2
If I<regex> B<did not> match, then I<on_fail> is called (and is given
Packit 9002b2
C<$date> and also I<label> if it was defined). Any return
Packit 9002b2
value is ignored and the next thing is for the single
Packit 9002b2
parser to return C<undef>.
Packit 9002b2
Packit 9002b2
If I<regex> B<did> match, then I<on_match> is called with
Packit 9002b2
the same arguments as would be given to I<on_fail>. The
Packit 9002b2
return value is similarly ignored, but we then move to step
Packit 9002b2
4 rather than exiting the parser.
Packit 9002b2
Packit 9002b2
=item 4
Packit 9002b2
Packit 9002b2
I<postprocess> is called with C<$date> and a filled out
Packit 9002b2
C<$p>. The return value is taken as a indication of whether
Packit 9002b2
the parse was a success or not. If it wasn't a success then
Packit 9002b2
the single parser will exit at this point, returning undef.
Packit 9002b2
Packit 9002b2
=item 5
Packit 9002b2
Packit 9002b2
C<< DateTime->new() >> is called and the user is given the
Packit 9002b2
resultant C<DateTime> object.
Packit 9002b2
Packit 9002b2
=back
Packit 9002b2
Packit 9002b2
See the section on L<error handling|/"ERROR HANDLING AND BAD PARSES">
Packit 9002b2
regarding the C<undef>s mentioned above.
Packit 9002b2
Packit 9002b2
=head2 For Multiple Specifications
Packit 9002b2
Packit 9002b2
With multiple specifications:
Packit 9002b2
Packit 9002b2
User calls parser:
Packit 9002b2
Packit 9002b2
      my $dt = $class->complex_parse( $string );
Packit 9002b2
Packit 9002b2
=over 4
Packit 9002b2
Packit 9002b2
=item 1
Packit 9002b2
Packit 9002b2
The overall I<preprocess>or is called and is given C<$string>
Packit 9002b2
and the hashref C<$p> (identically to the per parser
Packit 9002b2
I<preprocess> mentioned in the previous flow).
Packit 9002b2
Packit 9002b2
If the callback modifies C<$p> then a B<copy> of C<$p> is
Packit 9002b2
given to each of the individual parsers.  This is so parsers
Packit 9002b2
won't accidentally pollute each other's workspace.
Packit 9002b2
Packit 9002b2
=item 2
Packit 9002b2
Packit 9002b2
If an appropriate length specific parser is found, then it
Packit 9002b2
is called and the single parser flow (see the previous
Packit 9002b2
section) is followed, and the parser is given a copy of
Packit 9002b2
C<$p> and the return value of the overall I<preprocess>or as
Packit 9002b2
C<$date>.
Packit 9002b2
Packit 9002b2
If a C<DateTime> object was returned so we go straight back
Packit 9002b2
to the user.
Packit 9002b2
Packit 9002b2
If no appropriate parser was found, or the parser returned
Packit 9002b2
C<undef>, then we progress to step 3!
Packit 9002b2
Packit 9002b2
=item 3
Packit 9002b2
Packit 9002b2
Any non-I<length> based parsers are tried in the order they
Packit 9002b2
were specified.
Packit 9002b2
Packit 9002b2
For each of those the single specification flow above is
Packit 9002b2
performed, and is given a copy of the output from the
Packit 9002b2
overall preprocessor.
Packit 9002b2
Packit 9002b2
If a real C<DateTime> object is returned then we exit back
Packit 9002b2
to the user.
Packit 9002b2
Packit 9002b2
If no parser could parse, then an error is thrown.
Packit 9002b2
Packit 9002b2
=back
Packit 9002b2
Packit 9002b2
See the section on L<error handling|/ERROR HANDLING AND BAD PARSES>
Packit 9002b2
regarding the C<undef>s mentioned above.
Packit 9002b2
Packit 9002b2
=head1 METHODS
Packit 9002b2
Packit 9002b2
In the general course of things you won't need any of the
Packit 9002b2
methods. Life often throws unexpected things at us so the
Packit 9002b2
methods are all available for use.
Packit 9002b2
Packit 9002b2
=head2 import
Packit 9002b2
Packit 9002b2
C<import()> is a wrapper for C<create_class()>. If you
Packit 9002b2
specify the I<class> option (see documentation for
Packit 9002b2
C<create_class()>) it will be ignored.
Packit 9002b2
Packit 9002b2
=head2 create_class
Packit 9002b2
Packit 9002b2
This method can be used as the runtime equivalent of
Packit 9002b2
C<import()>. That is, it takes the exact same parameters as
Packit 9002b2
when one does:
Packit 9002b2
Packit 9002b2
   use DateTime::Format::Builder ( blah blah blah )
Packit 9002b2
Packit 9002b2
That can be (almost) equivalently written as:
Packit 9002b2
Packit 9002b2
   use DateTime::Format::Builder;
Packit 9002b2
   DateTime::Format::Builder->create_class( blah blah blah );
Packit 9002b2
Packit 9002b2
The difference being that the first is done at compile time
Packit 9002b2
while the second is done at run time.
Packit 9002b2
Packit 9002b2
In the tutorial I said there were only two parameters at
Packit 9002b2
present. I lied. There are actually three of them.
Packit 9002b2
Packit 9002b2
=over 4
Packit 9002b2
Packit 9002b2
=item *
Packit 9002b2
Packit 9002b2
B<parsers> takes a hashref of methods and their parser
Packit 9002b2
specifications. See the
Packit 9002b2
L<DateTime::Format::Builder::Tutorial> for details.
Packit 9002b2
Packit 9002b2
Note that if you define a subroutine of the same name as one
Packit 9002b2
of the methods you define here, an error will be thrown.
Packit 9002b2
Packit 9002b2
=item *
Packit 9002b2
Packit 9002b2
B<constructor> determines whether and how to create a
Packit 9002b2
C<new()> function in the new class. If given a true value, a
Packit 9002b2
constructor is created. If given a false value, one isn't.
Packit 9002b2
Packit 9002b2
If given an anonymous sub or a reference to a sub then that
Packit 9002b2
is used as C<new()>.
Packit 9002b2
Packit 9002b2
The default is C<1> (that is, create a constructor using
Packit 9002b2
our default code which simply creates a hashref and blesses
Packit 9002b2
it).
Packit 9002b2
Packit 9002b2
If your class defines its own C<new()> method it will not be
Packit 9002b2
overwritten. If you define your own C<new()> and B<also> tell
Packit 9002b2
Builder to define one an error will be thrown.
Packit 9002b2
Packit 9002b2
=item *
Packit 9002b2
Packit 9002b2
B<verbose> takes a value. If the value is undef, then
Packit 9002b2
logging is disabled. If the value is a filehandle then
Packit 9002b2
that's where logging will go. If it's a true value, then
Packit 9002b2
output will go to C<STDERR>.
Packit 9002b2
Packit 9002b2
Alternatively, call C<$DateTime::Format::Builder::verbose()>
Packit 9002b2
with the relevant value. Whichever value is given more
Packit 9002b2
recently is adhered to.
Packit 9002b2
Packit 9002b2
Be aware that verbosity is a global wide setting.
Packit 9002b2
Packit 9002b2
=item *
Packit 9002b2
Packit 9002b2
B<class> is optional and specifies the name of the class in
Packit 9002b2
which to create the specified methods.
Packit 9002b2
Packit 9002b2
If using this method in the guise of C<import()> then this
Packit 9002b2
field will cause an error so it is only of use when calling
Packit 9002b2
as C<create_class()>.
Packit 9002b2
Packit 9002b2
=item *
Packit 9002b2
Packit 9002b2
B<version> is also optional and specifies the value to give
Packit 9002b2
C<$VERSION> in the class. It's generally not recommended
Packit 9002b2
unless you're combining with the I<class> option. A
Packit 9002b2
C<ExtUtils::MakeMaker> / C<CPAN> compliant version
Packit 9002b2
specification is much better.
Packit 9002b2
Packit 9002b2
=back
Packit 9002b2
Packit 9002b2
In addition to creating any of the methods it also creates a
Packit 9002b2
C<new()> method that can instantiate (or clone) objects.
Packit 9002b2
Packit 9002b2
=head1 SUBCLASSING
Packit 9002b2
Packit 9002b2
In the rest of the documentation I've often lied in order to
Packit 9002b2
get some of the ideas across more easily. The thing is, this
Packit 9002b2
module's very flexible. You can get markedly different
Packit 9002b2
behaviour from simply subclassing it and overriding some
Packit 9002b2
methods.
Packit 9002b2
Packit 9002b2
=head2 create_method
Packit 9002b2
Packit 9002b2
Given a parser coderef, returns a coderef that is suitable
Packit 9002b2
to be a method.
Packit 9002b2
Packit 9002b2
The default action is to call C<on_fail()> in the event of a
Packit 9002b2
non-parse, but you can make it do whatever you want.
Packit 9002b2
Packit 9002b2
=head2 on_fail
Packit 9002b2
Packit 9002b2
This is called in the event of a non-parse (unless you've
Packit 9002b2
overridden C<create_method()> to do something else.
Packit 9002b2
Packit 9002b2
The single argument is the input string. The default action
Packit 9002b2
is to call C<croak()>. Above, where I've said parsers or
Packit 9002b2
methods throw errors, this is the method that is doing the
Packit 9002b2
error throwing.
Packit 9002b2
Packit 9002b2
You could conceivably override this method to, say, return
Packit 9002b2
C<undef>.
Packit 9002b2
Packit 9002b2
=head1 USING BUILDER OBJECTS aka USERS USING BUILDER
Packit 9002b2
Packit 9002b2
The methods listed in the L<METHODS> section are all you
Packit 9002b2
generally need when creating your own class. Sometimes
Packit 9002b2
you may not want a full blown class to parse something just
Packit 9002b2
for this one program. Some methods are provided to make that
Packit 9002b2
task easier.
Packit 9002b2
Packit 9002b2
=head2 new
Packit 9002b2
Packit 9002b2
The basic constructor. It takes no arguments, merely returns
Packit 9002b2
a new C<DateTime::Format::Builder> object.
Packit 9002b2
Packit 9002b2
    my $parser = DateTime::Format::Builder->new();
Packit 9002b2
Packit 9002b2
If called as a method on an object (rather than as a class
Packit 9002b2
method), then it clones the object.
Packit 9002b2
Packit 9002b2
    my $clone = $parser->new();
Packit 9002b2
Packit 9002b2
=head2 clone
Packit 9002b2
Packit 9002b2
Provided for those who prefer an explicit C<clone()> method
Packit 9002b2
rather than using C<new()> as an object method.
Packit 9002b2
Packit 9002b2
    my $clone_of_clone = $clone->clone();
Packit 9002b2
Packit 9002b2
=head2 parser
Packit 9002b2
Packit 9002b2
Given either a single or multiple parser specification, sets
Packit 9002b2
the object to have a parser based on that specification.
Packit 9002b2
Packit 9002b2
    $parser->parser(
Packit 9002b2
	regex  => qr/^ (\d{4}) (\d\d) (\d\d) $/x;
Packit 9002b2
	params => [qw( year    month  day    )],
Packit 9002b2
    );
Packit 9002b2
Packit 9002b2
The arguments given to C<parser()> are handed directly to
Packit 9002b2
C<create_parser()>. The resultant parser is passed to
Packit 9002b2
C<set_parser()>.
Packit 9002b2
Packit 9002b2
If called as an object method, it returns the object.
Packit 9002b2
Packit 9002b2
If called as a class method, it creates a new object, sets
Packit 9002b2
its parser and returns that object.
Packit 9002b2
Packit 9002b2
=head2 set_parser
Packit 9002b2
Packit 9002b2
Sets the parser of the object to the given parser.
Packit 9002b2
Packit 9002b2
   $parser->set_parser( $coderef );
Packit 9002b2
Packit 9002b2
Note: this method does not take specifications. It also does
Packit 9002b2
not take anything except coderefs. Luckily, coderefs are
Packit 9002b2
what most of the other methods produce.
Packit 9002b2
Packit 9002b2
The method return value is the object itself.
Packit 9002b2
Packit 9002b2
=head2 get_parser
Packit 9002b2
Packit 9002b2
Returns the parser the object is using.
Packit 9002b2
Packit 9002b2
   my $code = $parser->get_parser();
Packit 9002b2
Packit 9002b2
=head2 parse_datetime
Packit 9002b2
Packit 9002b2
Given a string, it calls the parser and returns the
Packit 9002b2
C<DateTime> object that results.
Packit 9002b2
Packit 9002b2
   my $dt = $parser->parse_datetime( "1979 07 16" );
Packit 9002b2
Packit 9002b2
The return value, if not a C<DateTime> object, is whatever
Packit 9002b2
the parser wants to return. Generally this means that if the
Packit 9002b2
parse failed an error will be thrown.
Packit 9002b2
Packit 9002b2
=head2 format_datetime
Packit 9002b2
Packit 9002b2
If you call this function, it will throw an errror.
Packit 9002b2
Packit 9002b2
=head1 LONGER EXAMPLES
Packit 9002b2
Packit 9002b2
Some longer examples are provided in the distribution. These
Packit 9002b2
implement some of the common parsing DateTime modules using
Packit 9002b2
Builder. Each of them are, or were, drop in replacements for
Packit 9002b2
the modules at the time of writing them.
Packit 9002b2
Packit 9002b2
=head1 THANKS
Packit 9002b2
Packit 9002b2
Dave Rolsky (DROLSKY) for kickstarting the DateTime project,
Packit 9002b2
writing L<DateTime::Format::ICal> and
Packit 9002b2
L<DateTime::Format::MySQL>, and some much needed review.
Packit 9002b2
Packit 9002b2
Joshua Hoblitt (JHOBLITT) for the concept, some of the API,
Packit 9002b2
impetus for writing the multilength code (both one length with
Packit 9002b2
multiple parsers and single parser with multiple lengths),
Packit 9002b2
blame for the Regex custom constructor code,
Packit 9002b2
spotting a bug in Dispatch,
Packit 9002b2
and more much needed review.
Packit 9002b2
Packit 9002b2
Kellan Elliott-McCrea (KELLAN) for even more review,
Packit 9002b2
suggestions, L<DateTime::Format::W3CDTF> and the encouragement to
Packit 9002b2
rewrite these docs almost 100%!
Packit 9002b2
Packit 9002b2
Claus FE<auml>rber (CFAERBER) for having me get around to
Packit 9002b2
fixing the auto-constructor writing, providing the
Packit 9002b2
'args'/'self' patch, and suggesting the multi-callbacks.
Packit 9002b2
Packit 9002b2
Rick Measham (RICKM) for L<DateTime::Format::Strptime>
Packit 9002b2
which Builder now supports.
Packit 9002b2
Packit 9002b2
Matthew McGillis for pointing out that C<on_fail> overriding
Packit 9002b2
should be simpler.
Packit 9002b2
Packit 9002b2
Simon Cozens (SIMON) for saying it was cool.
Packit 9002b2
Packit 9002b2
=head1 SUPPORT
Packit 9002b2
Packit 9002b2
Support for this module is provided via the datetime@perl.org email
Packit 9002b2
list. See http://lists.perl.org/ for more details.
Packit 9002b2
Packit 9002b2
Alternatively, log them via the CPAN RT system via the web or email:
Packit 9002b2
Packit 9002b2
    http://rt.cpan.org/NoAuth/ReportBug.html?Queue=DateTime%3A%3AFormat%3A%3ABuilder
Packit 9002b2
    bug-datetime-format-builder@rt.cpan.org
Packit 9002b2
Packit 9002b2
This makes it much easier for me to track things and thus means
Packit 9002b2
your problem is less likely to be neglected.
Packit 9002b2
Packit 9002b2
=head1 SEE ALSO
Packit 9002b2
Packit 9002b2
C<datetime@perl.org> mailing list.
Packit 9002b2
Packit 9002b2
http://datetime.perl.org/
Packit 9002b2
Packit 9002b2
L<perl>, L<DateTime>, L<DateTime::Format::Builder::Tutorial>,
Packit 9002b2
L<DateTime::Format::Builder::Parser>
Packit 9002b2
Packit 9002b2
=head1 AUTHORS
Packit 9002b2
Packit 9002b2
=over 4
Packit 9002b2
Packit 9002b2
=item *
Packit 9002b2
Packit 9002b2
Dave Rolsky <autarch@urth.org>
Packit 9002b2
Packit 9002b2
=item *
Packit 9002b2
Packit 9002b2
Iain Truskett
Packit 9002b2
Packit 9002b2
=back
Packit 9002b2
Packit 9002b2
=head1 COPYRIGHT AND LICENSE
Packit 9002b2
Packit 9002b2
This software is Copyright (c) 2013 by Dave Rolsky.
Packit 9002b2
Packit 9002b2
This is free software, licensed under:
Packit 9002b2
Packit 9002b2
  The Artistic License 2.0 (GPL Compatible)
Packit 9002b2
Packit 9002b2
=cut