# You may distribute under the terms of either the GNU General Public License # or the Artistic License (the same terms as Perl itself) # # Copyright (C) 2011 - Anthony J. Lucas - kaoyoriketsu@ansoni.com package Criteria::DateTime; use parent qw( Criteria::Compile ); use strict; use warnings; use DateTime ( ); use DateTime::Duration ( ); use Criteria::Compile ( ); #INIT CONFIG / VARS my $DATETIME_GRAMMAR = { Criteria::Compile::TYPE_DYNAMIC() => { qw/^(.*)_before$/ => qw/_gen_before_sub/, qw/^(.*)_after$/ => qw/_gen_after_sub/, qw/^(.*)_sooner_than$/ => qw/_gen_sooner_than_sub/, qw/^(.*)_later_than$/ => qw/_gen_later_than_sub/ } }; my $DURATION_GRAMMAR = { Criteria::Compile::TYPE_DYNAMIC() => { qw/^(.*)_longer_than$/ => qw/_gen_longer_than_sub/, qw/^(.*)_shorter_than$/ => qw/_gen_shorter_than_sub/ } }; #INITIALISATION ROUTINES sub _init { my ($self, $crit, $nocomp) = @_; $self->SUPER::_init($crit, 1); #define datetime grammara $self->define_datetime_grammar(); $self->define_duration_grammar(); #validate any criteria supplied if ($crit and !$nocomp) { die('Error: Failed to compile criteria.') unless ($self->compile()); } return 1; } sub define_datetime_grammar { Criteria::Compile::_define_grammar_dtbl($_[0], $DATETIME_GRAMMAR); } sub define_duration_grammar { Criteria::Compile::_define_grammar_dtbl($_[0], $DURATION_GRAMMAR); } #GRAMMAR HANDLER ROUTINES *getter = \&Criteria::Compile::getter; sub _dt_to_unix { my $dt = $_[0]; #convert datetime to unixtime $dt = $dt->epoch() if (ref($dt) eq 'DateTime'); #return unixtime or undef return ($dt =~ /^\d+$/) ? $dt : undef; } sub _del_to_dur { my $del = $_[0]; #convert delta to duration return $del if (ref($del) eq 'DateTime::Duration'); return DateTime::Duration->new(%$del) if (ref($del) eq 'HASH'); } sub _gen_before_sub { my ($context, $val, $attr) = @_; #check arguments die sprintf(Criteria::Compile::HANDLER_DIE_MSG(), 'before', 'No attribute supplied.') unless ($attr); #check value is usable for comparison die sprintf(Criteria::Compile::HANDLER_DIE_MSG(), 'before', 'Value not a valid datetime or unixtime value') unless (($val = _dt_to_unix($val)) ne ''); #return handler sub my $getter = $context->{getter}; return sub { return (ref($_[0]) and (local $_ = $getter->($_[0], $attr))) ? ($_->epoch() < $val) : 0; }; } sub _gen_after_sub { my ($context, $val, $attr) = @_; #check arguments die sprintf(Criteria::Compile::HANDLER_DIE_MSG(), 'after', 'No attribute supplied.') unless ($attr); #check value is usable for comparison die sprintf(Criteria::Compile::HANDLER_DIE_MSG(), 'after', 'Value not a valid datetime or unixtime value') unless (($val = _dt_to_unix($val)) ne ''); #return handler sub my $getter = $context->{getter}; return sub { return (ref($_[0]) and (local $_ = $getter->($_[0], $attr))) ? ($_->epoch() > $val) : 0; }; } sub _gen_sooner_than_sub { my ($context, $val, $attr) = @_; #check arguments die sprintf(Criteria::Compile::HANDLER_DIE_MSG(), 'sooner_than', 'No attribute supplied.') unless ($attr); #check value is usable for comparison die sprintf(Criteria::Compile::HANDLER_DIE_MSG(), 'sooner_than', 'Value not a valid duration value') unless (ref($val = _del_to_dur($val))); #return handler sub my $getter = $context->{getter}; Carp::croak('Getter not defined!') unless ($getter); return sub { return (ref($_[0]) and (local $_ = $getter->($_[0], $attr))) ? ($_->epoch() < DateTime->now()->add_duration($val)->epoch()) : 0; }; } sub _gen_later_than_sub { my ($context, $val, $attr) = @_; #check arguments die sprintf(Criteria::Compile::HANDLER_DIE_MSG(), 'later_than', 'No attribute supplied.') unless ($attr); #check value is usable for comparison die sprintf(Criteria::Compile::HANDLER_DIE_MSG(), 'later_than', 'Value not a valid duration value') unless (ref($val = _del_to_dur($val))); #return handler sub my $getter = $context->{getter}; return sub { return (ref($_[0]) and (local $_ = $getter->($_[0], $attr))) ? ($_->epoch() > DateTime->now()->add_duration($val)->epoch()) : 0; }; } sub _gen_shorter_than_sub { my ($context, $val, $attr) = @_; #check arguments die sprintf(Criteria::Compile::HANDLER_DIE_MSG(), 'shorter_than', 'No attribute supplied.') unless ($attr); #check value is usable for comparison die sprintf(Criteria::Compile::HANDLER_DIE_MSG(), 'shorter_than', 'Value not a valid duration value') unless (ref($val = _del_to_dur($val))); #return handler sub my $getter = $context->{getter}; return sub { return (ref($_[0]) and (local $_ = $getter->($_[0], $attr))) ? ($val->clone()->subtract_duration($_)->is_positive()) : 0; }; } sub _gen_longer_than_sub { my ($context, $val, $attr) = @_; #check arguments die sprintf(Criteria::Compile::HANDLER_DIE_MSG(), 'longer_than', 'No attribute supplied.') unless ($attr); #check value is usable for comparison die sprintf(Criteria::Compile::HANDLER_DIE_MSG(), 'longer_than', 'Value not a valid duration value') unless (ref($val = _del_to_dur($val))); #return handler sub my $getter = $context->{getter}; return sub { return (ref($_[0]) and (local $_ = $getter->($_[0], $attr))) ? ($_->clone()->subtract_duration($val)->is_positive()) : 0; }; } 1;