From 47bb99149685d8362c443b9a99daa972b8bd971f Mon Sep 17 00:00:00 2001 From: apirak Date: Wed, 6 May 2026 15:05:48 +0700 Subject: [PATCH] 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 Signed-off-by: Lucas Gass (cherry picked from commit 9c38d74c98488cabc882fa180927077d9cc8ec86) Signed-off-by: Jacob O'Mara Signed-off-by: Wainui Witika-Park --- Koha/Calendar.pm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Koha/Calendar.pm b/Koha/Calendar.pm index b10ff76fd0..354ed3c307 100644 --- a/Koha/Calendar.pm +++ b/Koha/Calendar.pm @@ -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 ); }