From a30d3ae82f9b9dc587f30556fa59540e0d56e0f0 Mon Sep 17 00:00:00 2001 From: Marcel de Rooy Date: Mon, 6 Jul 2015 14:20:07 +0200 Subject: [PATCH] Bug 14494: Terribly slow checkout caused by DateTime->new in far future Content-Type: text/plain; charset=utf-8 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 is now done in the floating timezone. [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: [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). --- C4/Circulation.pm | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/C4/Circulation.pm b/C4/Circulation.pm index de4b299..634e4ad 100644 --- a/C4/Circulation.pm +++ b/C4/Circulation.pm @@ -768,20 +768,21 @@ sub CanBookBeIssued { $issuingimpossible{EXPIRED} = 1; } else { my ($y, $m, $d) = split /-/,$borrower->{'dateexpiry'}; - if ($y && $m && $d) { # are we really writing oinvalid dates to borrs + if ($y && $m && $d) { # are we really writing invalid dates to borrs my $expiry_dt = DateTime->new( year => $y, month => $m, day => $d, - time_zone => C4::Context->tz, + time_zone => 'floating', #prevent trouble with future dates in named timezones (see bug 13242, 14494) ); $expiry_dt->truncate( to => 'day'); my $today = $now->clone()->truncate(to => 'day'); + $today->set_time_zone( 'floating' ); if (DateTime->compare($today, $expiry_dt) == 1) { $issuingimpossible{EXPIRED} = 1; } } else { - carp("Invalid expity date in borr"); + carp("Invalid expiry date in borr"); $issuingimpossible{EXPIRED} = 1; } } @@ -3457,10 +3458,11 @@ 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' ); + my $expiry_dt = dt_from_string( $borrower->{dateexpiry}, 'iso', 'floating'); $expiry_dt->set( hour => 23, minute => 59); - if ( DateTime->compare( $datedue, $expiry_dt ) == 1 ) { - $datedue = $expiry_dt->clone; + 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 ); } } -- 1.7.10.4