DateTimeX-Lite

 view release on metacpan or  search on metacpan

lib/DateTimeX/Lite/Arithmetic.pm  view on Meta::CPAN

        my $class = ref $dt;
        my $dt_string = overload::StrVal($dt);

        Carp::croak( "Cannot add $dur to a $class object ($dt_string).\n"
                     . " Only a DateTimeX::Lite::Duration object can "
                     . " be added to a $class object." );
    }

    return $dt->clone->add_duration($dur);
}

sub _subtract_overload
{
    my ( $date1, $date2, $reversed ) = @_;

    if ($reversed)
    {
        ( $date2, $date1 ) = ( $date1, $date2 );
    }

    if ( blessed $date2 && $date2->isa( 'DateTimeX::Lite::Duration' ) )
    {
        my $new = $date1->clone;
        $new->add_duration( $date2->inverse );
        return $new;
    }
    elsif ( blessed $date2 && $date2->isa( 'DateTimeX::Lite' ) )
    {
        return $date1->subtract_datetime($date2);
    }
    else
    {
        my $class = ref $date1;
        my $dt_string = overload::StrVal($date1);

        Carp::croak( "Cannot subtract $date2 from a $class object ($dt_string).\n"
                     . " Only a DateTimeX::Lite::Duration or DateTimeX::Lite object can "
                     . " be subtracted from a $class object." );
    }
}

sub add { return shift->add_duration( DateTimeX::Lite::Duration->new(@_) ) }

sub subtract { return shift->subtract_duration( DateTimeX::Lite::Duration->new(@_) ) }

sub subtract_duration { return $_[0]->add_duration( $_[1]->inverse ) }

    sub add_duration
    {
        my ($self, $dur) = @_;
        if (! blessed $dur || !$dur->isa('DateTimeX::Lite::Duration')) {
            Carp::croak("Duration is not a DateTimeX::Lite::Duration object");
        }

        # simple optimization
        return $self if $dur->is_zero;

        my %deltas = $dur->deltas;

        # This bit isn't quite right since DateTimeX::Lite::Infinite::Future -
        # infinite duration should NaN
        foreach my $val ( values %deltas )
        {
            my $inf;
            if ( $val == &DateTimeX::Lite::INFINITY )
            {
                $inf = DateTimeX::Lite::Infinite::Future->new;
            }
            elsif ( $val == &DateTimeX::Lite::NEG_INFINITY )
            {
                $inf = DateTimeX::Lite::Infinite::Past->new;
            }

            if ($inf)
            {
                %$self = %$inf;
                bless $self, blessed $inf;

                return $self;
            }
        }

        return $self if $self->is_infinite;

        if ( $deltas{days} )
        {
            $self->{local_rd_days} += $deltas{days};

            $self->{utc_year} += int( $deltas{days} / 365 ) + 1;
        }

        if ( $deltas{months} )
        {
            # For preserve mode, if it is the last day of the month, make
            # it the 0th day of the following month (which then will
            # normalize back to the last day of the new month).
            my ($y, $m, $d) = ( $dur->is_preserve_mode ?
                                DateTimeX::Lite::Util::rd2ymd( $self->{local_rd_days} + 1 ) :
                                DateTimeX::Lite::Util::rd2ymd( $self->{local_rd_days} )
                              );

            $d -= 1 if $dur->is_preserve_mode;

            if ( ! $dur->is_wrap_mode && $d > 28 )
            {
                # find the rd for the last day of our target month
                $self->{local_rd_days} = DateTimeX::Lite::Util::ymd2rd( $y, $m + $deltas{months} + 1, 0 );

                # what day of the month is it? (discard year and month)
                my $last_day = (DateTimeX::Lite::Util::rd2ymd( $self->{local_rd_days} ))[2];

                # if our original day was less than the last day,
                # use that instead
                $self->{local_rd_days} -= $last_day - $d if $last_day > $d;
            }
            else
            {
                $self->{local_rd_days} = DateTimeX::Lite::Util::ymd2rd( $y, $m + $deltas{months}, $d );
            }

            $self->{utc_year} += int( $deltas{months} / 12 ) + 1;



( run in 2.085 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )