From: Galen Charlton Date: Fri, 21 Sep 2018 18:30:01 +0000 (-0400) Subject: LP#1552778: make clean_ISO8601 recognize 'Z' as a timezone specifier X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=b1c3b925764f6d8bf7cfe8b9f9c9a4ebe4c09d04;p=evergreen%2Fequinox.git LP#1552778: make clean_ISO8601 recognize 'Z' as a timezone specifier Prior to this patch, clean_ISO8601 would ignore 'Z' as a timezone specifier (e.g., '2018-09-21T15:34:21Z') and treat it as if the timestamp were in the server's time zone, leading to incorrect results (e.g., '2018-09-21T15:34:21-04:00') unless user, client, and server all happen to be in UTC+0. In particular, this allows date strings emitted by the JavaScript Date object's toISOString() method to be correctly parsed, as those strings invariably use 'Z' as the timezone specifier. To test ------- [1] Apply patch. [2] Verify that regression test in t/14-OpenILS-Utils.t passes. Signed-off-by: Galen Charlton Signed-off-by: Kathy Lussier --- diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Utils/DateTime.pm b/Open-ILS/src/perlmods/lib/OpenILS/Utils/DateTime.pm index 69fec7ae5e..05f0883bcd 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Utils/DateTime.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Utils/DateTime.pm @@ -253,6 +253,8 @@ sub clean_ISO8601 { my $z; if ($date =~ /([-+]{1})([0-9]{1,2})(?::?([0-9]{1,2}))*\s*$/o) { $z = sprintf('%s%0.2d%0.2d',$1,$2,$3) + } elsif ($date =~ /Z\s*$/) { + $z = "+00:00"; } else { $z = DateTime::TimeZone::offset_as_string( DateTime::TimeZone diff --git a/Open-ILS/src/perlmods/t/14-OpenILS-Utils.t b/Open-ILS/src/perlmods/t/14-OpenILS-Utils.t index ec164a7a79..a341f3e815 100644 --- a/Open-ILS/src/perlmods/t/14-OpenILS-Utils.t +++ b/Open-ILS/src/perlmods/t/14-OpenILS-Utils.t @@ -1,6 +1,6 @@ #!perl -T -use Test::More tests => 42; +use Test::More tests => 43; use Test::Warn; use DateTime::TimeZone; use DateTime::Format::ISO8601; @@ -110,14 +110,23 @@ is (OpenILS::Utils::DateTime::interval_to_seconds('1 month'), 2628000); is (OpenILS::Utils::DateTime::interval_to_seconds('1 year'), 31536000); is (OpenILS::Utils::DateTime::interval_to_seconds('1 year 1 second'), 31536001); -# get current timezone offset for future use -my $offset = DateTime::TimeZone::offset_as_string( - DateTime::TimeZone->new( name => 'local' )->offset_for_datetime( - DateTime::Format::ISO8601->new()->parse_datetime('2018-09-17') - ) - ); -$offset =~ s/^(.\d\d)(\d\d)+/$1:$2/; +sub get_offset { + # get current timezone offset for future use + my $offset = DateTime::TimeZone::offset_as_string( + DateTime::TimeZone->new( name => 'local' )->offset_for_datetime( + DateTime::Format::ISO8601->new()->parse_datetime('2018-09-17') + ) + ); + $offset =~ s/^(.\d\d)(\d\d)+/$1:$2/; + return $offset; +} is (OpenILS::Utils::DateTime::clean_ISO8601('20180917'), '2018-09-17T00:00:00', 'plain date converted to ISO8601 timestamp'); is (OpenILS::Utils::DateTime::clean_ISO8601('I am not a date'), 'I am not a date', 'non-date simply returned as is'); +my $offset = get_offset(); is (OpenILS::Utils::DateTime::clean_ISO8601('20180917 08:31:15'), "2018-09-17T08:31:15$offset", 'time zone added to date/time'); + +# force timezone to specific value to avoid a spurious +# pass if this test happens to be run in UTC +$ENV{TZ} = 'EST'; +is (OpenILS::Utils::DateTime::clean_ISO8601('2018-09-17T17:31:15Z'), "2018-09-17T17:31:15+00:00", 'interpret Z in timestamp correctly');