Bug 14494: Terribly slow checkout caused by DateTime->new in far future

An expiry date like 9999-12-31 in the local timezone will make DateTime
spend a lot of time (maybe 60 seconds) on date calculation. See the
DateTime documention on CPAN.
A calculation in floating (or alternatively in UTC) would only take
a few milliseconds.

This patch makes two changes in this regard:

[1] The compare between expiry date and today in CanBookBeIssued has been
    adjusted in Jonathan's patch. I am moving the compare to the floating
    timezone (as was done in my original patch). This removes a hardcoded
    9999.
[2] If ReturnBeforeExpiry is enabled, CalcDateDue compares the normal due
    date with the expiry date. The comparison is now done in the floating
    timezone. If the expiry date is before the due date, it is
    returned in the user context's timezone.

NOTE: The calls to set_time_zone moving to or from floating do not adjust
the local time.

TEST PLAN:
First without this patch (and the one from Jonathan):
[1] Set expiry date to 9999-12-31 for a patron.
[2] Enable ReturnBeforeExpiry.
[3] Checkout a book to this patron. This will be (very) slow.

Continue now with this patch applied:
[4] Check in the same book.
[5] Check it out again. Should be much faster.

Bonus test:
[6] Set borrower expiry date to today. Change relevant circulation rule
    to loan period of 21 hours. Test checking out with a manual due date
    /time just before today 23:59 and after that. In the second case the
    due date/time should become today 23:59 (note that 23:59 is not
    shown on the checkout form).

Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
Signed-off-by: Tomas Cohen Arazi <tomascohen@unc.edu.ar>
This commit is contained in:
Marcel de Rooy 2015-07-06 14:20:07 +02:00 committed by Tomas Cohen Arazi
parent 8d58acc565
commit 17d04c4619

View file

@ -767,11 +767,11 @@ sub CanBookBeIssued {
if ( !defined $borrower->{dateexpiry} || $borrower->{'dateexpiry'} eq '0000-00-00') {
$issuingimpossible{EXPIRED} = 1;
} else {
my $expiry_dt = dt_from_string( $borrower->{dateexpiry}, 'sql' );
my $expiry_dt = dt_from_string( $borrower->{dateexpiry}, 'sql', 'floating' );
$expiry_dt->truncate( to => 'day');
my $today = $now->clone()->truncate(to => 'day');
if ($expiry_dt->year < 9999 && DateTime->compare($today, $expiry_dt) == 1) {
$today->set_time_zone( 'floating' );
if ( DateTime->compare($today, $expiry_dt) == 1 ) {
$issuingimpossible{EXPIRED} = 1;
}
}
@ -3448,10 +3448,13 @@ sub CalcDateDue {
# if ReturnBeforeExpiry ON the datedue can't be after borrower expirydate
if ( C4::Context->preference('ReturnBeforeExpiry') ) {
my $expiry_dt = dt_from_string( $borrower->{dateexpiry}, 'iso' );
$expiry_dt->set( hour => 23, minute => 59);
if ( DateTime->compare( $datedue, $expiry_dt ) == 1 ) {
$datedue = $expiry_dt->clone;
my $expiry_dt = dt_from_string( $borrower->{dateexpiry}, 'iso', 'floating');
if( $expiry_dt ) { #skip empty expiry date..
$expiry_dt->set( hour => 23, minute => 59);
my $d1= $datedue->clone->set_time_zone('floating');
if ( DateTime->compare( $d1, $expiry_dt ) == 1 ) {
$datedue = $expiry_dt->clone->set_time_zone( C4::Context->tz );
}
}
}