Bug 42545: Koha::Calendar::days_between skips holiday subtraction for end date if time is early

In Koha::Calendar::days_between, the holiday-subtraction loop uses a comparison
that includes time. If the end_dt is a holiday and its time is earlier than
the start_dt time (common in renewals), the loop terminates before processing
the end_dt, leading to an extra fine day.

This patch truncates both dates to the beginning of the day after cloning
and setting the time zone, ensuring the loop correctly processes all
calendar days between the two dates.

Test Plan:
1. Set 'finesCalendar' syspref to 'noFinesWhenClosed'.
2. Set 'CalculateFinesOnReturn' syspref to 'Yes'.
3. Set 'finesMode' syspref to 'Production'.
4. Define a special holiday for today in the library calendar.
5. Identify an overdue item for a patron. Manually set its 'date_due' in the
   database to several days ago with a time of 23:59:00.
6. Renew the item today at any time BEFORE 23:59:00 (e.g., 10:00 AM).
7. Observe that an extra day of fine is charged because today (the holiday)
   was not subtracted.
8. Apply this patch.
9. Repeat the test and observe that the holiday is now correctly subtracted.

Signed-off-by: Martin Renvoize <martin.renvoize@openfifth.co.uk>
Signed-off-by: Lucas Gass <lucas@bywatersolutions.com>
(cherry picked from commit 9c38d74c98)
Signed-off-by: Jacob O'Mara <Jacob.omara@openfifth.co.uk>
Signed-off-by: Wainui Witika-Park <wainuiwitikapark@catalyst.net.nz>
This commit is contained in:
apirak 2026-05-06 15:05:48 +07:00 committed by Wainui Witika-Park
parent da718a2a57
commit 47bb991496
No known key found for this signature in database
GPG Key ID: 2D0A6AB5DAF1B78D
1 changed files with 3 additions and 2 deletions

View File

@ -342,9 +342,10 @@ sub days_between {
my $end_dt = shift;
# Change time zone for date math and swap if needed
$start_dt = $start_dt->clone->set_time_zone('floating');
$end_dt = $end_dt->clone->set_time_zone('floating');
$start_dt = $start_dt->clone->set_time_zone('floating')->truncate( to => 'day' );
$end_dt = $end_dt->clone->set_time_zone('floating')->truncate( to => 'day' );
if ( $start_dt->compare($end_dt) > 0 ) {
( $start_dt, $end_dt ) = ( $end_dt, $start_dt );
}