App-Oozie

 view release on metacpan or  search on metacpan

lib/App/Oozie/Date.pm  view on Meta::CPAN

package App::Oozie::Date;

use 5.014;
use strict;
use warnings;

our $VERSION = '0.020'; # VERSION

use namespace::autoclean -except => [qw/_options_data _options_config/];

use App::Oozie::Constants qw(
    DATE_PATTERN
    SHORTCUT_METHODS
);
use Carp qw( croak );
use DateTime;
use DateTime::Format::Strptime;
use DateTime::Format::Duration;
use Moo;
use Types::Standard qw( Str );

has strp => (
    is      => 'ro',
    default => sub {
        my $self = shift;
        DateTime::Format::Strptime->new(
                pattern   => DATE_PATTERN,
                time_zone => $self->timezone,
                on_error  => 'croak',
            );
    },
    lazy => 1,
);

has strp_silent => (
    is      => 'ro',
    default => sub {
        my $self = shift;
        DateTime::Format::Strptime->new(
                pattern   => DATE_PATTERN,
                time_zone => $self->timezone,
            );
    },
    lazy => 1,
);

has timezone => (
    is       => 'rw',
    isa      => Str,
    required => 1,
);

sub today {
    my $self  = shift;
    return $self->_stringify_dt( DateTime->today );
}

sub tomorrow {
    my $self  = shift;
    my $today = DateTime->today;
    $today->add( days => 1 );
    return $self->_stringify_dt( $today );
}

sub yesterday {
    my $self  = shift;
    my $today = DateTime->today;
    $today->subtract( days => 1 );
    return $self->_stringify_dt( $today );
}

sub diff {
    my $self   = shift;
    my $date_1 = shift || croak 'First date is missing';
    my $date_2 = shift || croak 'Second date is missing';

    my $dt1 = $self->strp->parse_datetime( $date_1 );
    my $dt2 = $self->strp->parse_datetime( $date_2 );
    my $dur = $dt1->subtract_datetime( $dt2 );

    my $days = DateTime::Format::Duration
                ->new( pattern => '%j')
                ->format_duration( $dur );
    return $days;
}

sub is_valid {
    my $self = shift;
    my $date = shift || croak 'Date is missing';
    my $rv = $self->strp_silent->parse_datetime( $date );
    if ( ! $rv ) {
        warn sprintf 'The date value `%s` is invalid: %s',
                        $date,
                        $self->strp->errmsg;
    }
    return $rv;
}

sub move {
    my $self = shift;
    my $date = shift || croak 'No date parameter was specified';
    my $by   = shift || croak 'No days to shift by were specified';

    my $dt = $self->strp->parse_datetime( $date );
    $dt->add( days => $by );

    return $self->_stringify_dt( $dt );
}

sub _stringify_dt {
    my $self = shift;
    my $dt   = shift;
    return sprintf '%d-%02d-%02d',
                    map { $dt->$_ }
                    qw(
                        year
                        month
                        day
                    );
}

sub intersection {
    state $usage = sub {
        my $missing = shift;
        my $msg = 'Usage: intersection(first_start, first_end, second_start, second_end)';
        if ( $missing ) {
            $msg .= sprintf q{. You didn't specify `%s`},
                                $missing,
                    ;
        }
        croak $msg;
    };

    my $self          = shift;
    my $x_start       = shift || $usage->('first_start');
    my $x_end         = shift || $usage->('first_end');
    my $y_start       = shift || $usage->('second_start');
    my $y_end         = shift || $usage->('second_end');
    my $strp          = $self->strp;
    my $x_start_epoch = $strp->parse_datetime( $x_start )->epoch;
    my $x_end_epoch   = $strp->parse_datetime( $x_end   )->epoch;
    my $y_start_epoch = $strp->parse_datetime( $y_start )->epoch;
    my $y_end_epoch   = $strp->parse_datetime( $y_end   )->epoch;

    return if  $x_start_epoch > $x_end_epoch
            || $y_start_epoch > $y_end_epoch
            || $y_start_epoch > $x_end_epoch
            || $x_start_epoch > $y_end_epoch
    ;

    my $start = 0 < ($x_start_epoch <=> $y_start_epoch) ? $x_start_epoch : $y_start_epoch;
    my $end   = 0 > ($x_end_epoch   <=> $y_end_epoch  ) ? $x_end_epoch   : $y_end_epoch;

    return {
        start => $self->_stringify_dt( DateTime->from_epoch( epoch => $start ) ),
        end   => $self->_stringify_dt( DateTime->from_epoch( epoch => $end   ) ),
    };
}

sub epoch_yyyy_mm_dd_hh_mm_ss {
    my $self  = shift;
    my $epoch = shift || Carp::confess 'Epoch not specified!';
    my $strp  = DateTime::Format::Strptime->new(
                    pattern   => '%Y-%m-%d %H:%M:%S %Z',
                    time_zone => $self->timezone,
                    on_error  => 'croak',
                );
    return $strp->format_datetime(
                DateTime->from_epoch(
                    epoch     => $epoch,
                    time_zone => $self->timezone,
                )
            );
}

1;

__END__

=pod

=encoding UTF-8

=head1 NAME

App::Oozie::Date

=head1 VERSION

version 0.020

=head1 SYNOPSIS

    use App::Oozie::Date;
    my $d = App::Oozie::Date->new;

=head1 DESCRIPTION

Date related functions.

=head1 NAME

App::Oozie::Date - Date related functions.

=head1 Methods

=head2 diff

=head2 epoch_yyyy_mm_dd_hh_mm_ss

=head2 intersection

=head2 is_valid

=head2 move

=head2 today

=head2 tomorrow

=head2 yesterday

=head1 Accessors

=head2 Overridable from sub-classes

=head3 strp

=head3 strp_silent



( run in 0.749 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )