From dcb5a0bb8d8af4283cd9229b4d63c4dc5f98e265 Mon Sep 17 00:00:00 2001
From: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Date: Fri, 14 Jan 2022 09:07:58 +0000
Subject: [PATCH] Bug 29718: (QA follow-up) ISO 8601 allows +02 and +0200
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
Content-Type: text/plain; charset=utf-8

The UTC offset is appended to the time in the form:
    ±[hh]:[mm], ±[hh][mm], or ±[hh]

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
---
 Koha/DateUtils.pm |  6 +++---
 t/DateUtils.t     | 10 ++++++++--
 2 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/Koha/DateUtils.pm b/Koha/DateUtils.pm
index 0e8bd3c6fc..bba8938499 100644
--- a/Koha/DateUtils.pm
+++ b/Koha/DateUtils.pm
@@ -142,7 +142,7 @@ sub dt_from_string {
         die "Invalid dateformat parameter ($date_format)";
     }
 
-    # Add the faculative time part [hh:mm[:ss]]
+    # Add the facultative time part including time zone offset; ISO8601 allows +02 or +0200 too
     my $time_re .= qr{
             (
                 [Tt]?
@@ -159,7 +159,7 @@ sub dt_from_string {
                     (?<ampm>\w{2})
                 )?
                 (
-                    (?<utc>[Zz]$)|((?<offset>[\+|\-])(?<hours>[01][0-9]|2[0-3]):(?<minutes>[0-5][0-9]))
+                    (?<utc>[Zz]$)|((?<offset>[\+|\-])(?<hours>[01][0-9]|2[0-3]):?(?<minutes>[0-5][0-9])?)
                 )?
             )?
     }xms;
@@ -183,7 +183,7 @@ sub dt_from_string {
         }
         if ( $+{offset} ) {
             # If offset given, set inbound timezone using it.
-            $tz = DateTime::TimeZone->new( name => $+{offset} . $+{hours} . $+{minutes} );
+            $tz = DateTime::TimeZone->new( name => $+{offset} . $+{hours} . ( $+{minutes} || '00' ) );
         }
     } elsif ( $do_fallback && $date_string =~ $fallback_re ) {
         %dt_params = (
diff --git a/t/DateUtils.t b/t/DateUtils.t
index 7cfa982187..9e366994d5 100755
--- a/t/DateUtils.t
+++ b/t/DateUtils.t
@@ -144,7 +144,7 @@ like( $@, qr/.*does not match the date format \(rfc3339\).*/, 'dt_from_string sh
 
 # ISO string tests
 subtest 'dt_from_string - iso format' => sub {
-    plan tests => 5;
+    plan tests => 7;
 
     my $module_context = Test::MockModule->new('C4::Context');
     $module_context->mock(
@@ -175,8 +175,14 @@ subtest 'dt_from_string - iso format' => sub {
     # Sunday January 01, 2012 23:59:59 (UTC)
 
     $dt_iso = dt_from_string( '2012-01-01T23:59:59+02:00', 'iso' );
-    cmp_ok( $dt_iso->epoch(), 'eq', '1325455199', 'dt_from_string with offset' );
+    cmp_ok( $dt_iso->epoch(), 'eq', '1325455199', 'dt_from_string with offset +02:00' );
     # Sunday January 01, 2012 21:59:59 (UTC) == Sunday January 01, 2012 23:59:59 Europe/Athens (EET/+02:00)
+    # Allow +02 or +0200 too
+    $dt_iso = dt_from_string( '2012-01-01T23:59:59+02', 'iso' );
+    cmp_ok( $dt_iso->epoch(), 'eq', '1325455199', 'dt_from_string with offset +02' );
+    $dt_iso = dt_from_string( '2012-01-01T23:59:59+0200', 'iso' );
+    cmp_ok( $dt_iso->epoch(), 'eq', '1325455199', 'dt_from_string with offset +0200' );
+
 };
 
 # Return undef if passed mysql 0 dates
-- 
2.20.1