DT

 view release on metacpan or  search on metacpan

lib/DT.pm  view on Meta::CPAN

package DT;

use strict;
use warnings 'FATAL' => 'all';

use Carp qw();
use Scalar::Util qw(looks_like_number);
use Sub::Install;

use DateTime::Format::ISO8601;
use DateTime::Format::ISO8601::Format;

use parent 'DateTime::Moonpig';

our $VERSION = '0.5.0';

use overload
    '""'  => \&_dt_stringify,
    '=='  => \&_dt_int_eq,
    '!='  => \&_dt_int_ne,
    '<=>' => \&_dt_int_cmp,
    '<'   => \&_dt_int_lt,
    '<='  => \&_dt_int_le,
    '>'   => \&_dt_int_gt,
    '>='  => \&_dt_int_ge,
    'eq'  => \&_dt_str_eq,
    'ne'  => \&_dt_str_ne,
    'cmp' => \&_dt_str_cmp,
    'lt'  => \&_dt_str_lt,
    'le'  => \&_dt_str_le,
    'gt'  => \&_dt_str_gt,
    'ge'  => \&_dt_str_ge;

my $HAVE_PG;

sub new {
    my $class = shift;

    my $dt;

    if ( @_ == 1 ) {
        # Most probably Unix time, will croak if not
        if ( looks_like_number $_[0] ) {
            $dt = $class->SUPER::new(@_);
        }
        elsif ( not ref $_[0] ) {
            # May be ISO8601(ish) format used by PostgreSQL
            $dt = eval {
                $HAVE_PG || ($HAVE_PG = require DateTime::Format::Pg);
                DateTime::Format::Pg->parse_datetime($_[0]);
            };
            

            # May be a real ISO8601 format date/time
            $dt = eval { DateTime::Format::ISO8601->parse_datetime($_[0]) }
                if not $dt;
        }
    }

    # This will croak
    $dt = DateTime->new(@_) unless $dt;

    # Rebless into DT so our methods are called instead of DateTime
    return bless $dt, $class;
}

sub unix_time { $_[0]->epoch }

sub pg_timestamp_notz {
    Carp::croak("DateTime::Format::Pg is not installed")
        unless $HAVE_PG || ($HAVE_PG = require DateTime::Format::Pg);
    
    return DateTime::Format::Pg->format_timestamp_without_time_zone($_[0]);
}

sub pg_timestamp_tz {
    Carp::croak("DateTime::Format::Pg is not installed")
        unless $HAVE_PG || ($HAVE_PG = require DateTime::Format::Pg);
    
    return DateTime::Format::Pg->format_timestamptz($_[0]);
}

{
    for my $method (qw(
        add_duration subtract_duration
        truncate
        set set_time_zone set_year set_month set_day
        set_hour set_minute set_second set_nanosecond
    )) {
        Sub::Install::install_sub({
            code => sub {
                my $dt = shift;
                
                my $copy = $dt->clone;
                bless $copy, 'DateTime';
                
                $copy->$method(@_);
                
                bless $copy, ref $dt;
                
                return $copy;
            },
            as => $method,
        });
    }
}

sub TO_JSON {
    my ($self) = @_;
    
    return "$self";
}

############## PRIVATE METHODS BELOW ##############

sub _promote {
    my $side_b = $_[1];
    
    # Deliberately not catching errors here
    $side_b = DT->new($side_b)
        if not ref($side_b) or not $side_b->isa('DateTime');
    
    return ($_[0], $side_b, $_[2]);
}

sub _dt_stringify {
    return DateTime::Format::ISO8601::Format->new->format_datetime($_[0]);
}

sub _dt_int_eq {
    return undef unless defined $_[1];
    
    my ($side_a, $side_b) = _promote(@_);
    
    return DateTime::compare($side_a, $side_b) == 0;
}

sub _dt_int_cmp {



( run in 1.974 second using v1.01-cache-2.11-cpan-75ffa21a3d4 )