From 8caa4f251455d3dfa876ebecb70ddd5af1b30e5f Mon Sep 17 00:00:00 2001 From: Jonathan Druart Date: Sat, 22 Jun 2019 20:40:04 -0500 Subject: [PATCH] Bug 23079: Handle invalid timezones when adding/subtracting durations On Nov 3rd 2019, Brazil will skip from 00:00 to 1:00 (http://www.currenttimeonline.com/dst/dst.do?tz=America/Sao_Paulo), DateTime consider it as an invalid date. It is a problem when we are playing with dates without the time part (always 00:00). When we instantiate a DateTime (from dt_from_string) we are already handling this issue, and use the floating timezone (since bug 12669). The problem remains when we generate a DateTime then add or subtract a duration, which will result in an invalid date: DateTime->new(year => 2019, month => 12, day => 3, time_zone => 'America/Sao_Paulo')->subtract(days => 30); => Nov 3rd 2019, kaboom. We should replace all the problematic occurrences of dt_from_string->subtract (or ->add) with dt_from_string(undef, undef, 'floating'), to use the floating timezone and avoid the error. Actually there are not many of them, I have found only 3 that could produce real problems. The other occurrences are: - in tests => Not a big deal (for now) - called on a datetime, so it will explode if called at midnight 00:00:00 (and nobody should work at that time). Test plan: 0/ Define the timezone to 'America/Sao_Paulo' (in your koha-conf.xml file), restart_all 1/ Set a patron's expiry date to Dec 3rd 2019, and NotifyBorrowerDeparture to 30 (default value) 2/ See the checkouts page for this user => Without this patch you get "Invalid local time for date in time zone: America/Sao_Paulo" => With this patch apply the page displays correctly QA will review the 2 other occurrences. --- Koha/Patron.pm | 2 +- acqui/duplicate_orders.pl | 2 +- acqui/histsearch.pl | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Koha/Patron.pm b/Koha/Patron.pm index 04b54a3ed6..c051275550 100644 --- a/Koha/Patron.pm +++ b/Koha/Patron.pm @@ -622,7 +622,7 @@ sub is_going_to_expire { return 0 unless $delay; return 0 unless $self->dateexpiry; return 0 if $self->dateexpiry =~ '^9999'; - return 1 if dt_from_string( $self->dateexpiry )->subtract( days => $delay ) < dt_from_string->truncate( to => 'day' ); + return 1 if dt_from_string( $self->dateexpiry, undef, 'floating' )->subtract( days => $delay ) < dt_from_string(undef, undef, 'floating')->truncate( to => 'day' ); return 0; } diff --git a/acqui/duplicate_orders.pl b/acqui/duplicate_orders.pl index 549c8b495a..a4a02fc628 100755 --- a/acqui/duplicate_orders.pl +++ b/acqui/duplicate_orders.pl @@ -74,7 +74,7 @@ my $to_placed_on = unless ( $input->param('from') ) { # Fill the form with year-1 - $from_placed_on->subtract( years => 1 ); + $from_placed_on->set_time_zone('floating')->subtract( years => 1 ); } $filters->{from_placed_on} = output_pref( { dt => $from_placed_on, dateformat => 'iso', dateonly => 1 } ), diff --git a/acqui/histsearch.pl b/acqui/histsearch.pl index f5dca499c8..93bca344fd 100755 --- a/acqui/histsearch.pl +++ b/acqui/histsearch.pl @@ -94,7 +94,7 @@ my $from_placed_on = eval { dt_from_string( scalar $input->param('from') ) } || my $to_placed_on = eval { dt_from_string( scalar $input->param('to') ) } || dt_from_string; unless ( $input->param('from') ) { # Fill the form with year-1 - $from_placed_on->subtract( years => 1 ); + $from_placed_on->set_time_zone('floating')->subtract( years => 1 ); } $filters->{from_placed_on} = output_pref( { dt => $from_placed_on, dateformat => 'iso', dateonly => 1 } ), $filters->{to_placed_on} = output_pref( { dt => $to_placed_on, dateformat => 'iso', dateonly => 1 } ), -- 2.11.0