From 73e6d8142f985db74d39f0c8a271f2e4ba1755f4 Mon Sep 17 00:00:00 2001
From: Jonathan Druart <jonathan.druart@biblibre.com>
Date: Tue, 16 Sep 2014 13:15:57 +0200
Subject: [PATCH] [PASSED QA] Bug 12669: Centralize the timezone handle into Koha::DateUtils

This patch adds unit tests for the previous changes and centralize the
timezone handle into the Koha::DateUtils module.
Like that the behavior will affect all date manipulations using this
module (should be all dates in Koha).

Signed-off-by: Chris Cormack <chris@bigballofwax.co.nz>

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>
---
 Koha/DateUtils.pm                               |   22 ++++++++++++----
 Koha/Template/Plugin/KohaDates.pm               |    3 +-
 t/DateUtils.t                                   |   22 ++++++++++++++++-
 t/db_dependent/Koha_template_plugin_KohaDates.t |   30 +++++++++++++++++++----
 4 files changed, 63 insertions(+), 14 deletions(-)

diff --git a/Koha/DateUtils.pm b/Koha/DateUtils.pm
index 001d7ab..61877b9 100644
--- a/Koha/DateUtils.pm
+++ b/Koha/DateUtils.pm
@@ -58,9 +58,8 @@ sub dt_from_string {
     return DateTime::Format::DateParse->parse_datetime($date_string)
         if $date_string and $date_string =~ /^9999-/;
 
-    if ( !$tz ) {
-        $tz = C4::Context->tz;
-    }
+    my $dt;
+    $tz ||= C4::Context->tz;
     if ( !$date_format ) {
         $date_format = C4::Context->preference('dateformat');
     }
@@ -89,10 +88,21 @@ s/(\d{4})(\d{2})(\d{2})\s+(\d{2})(\d{2})(\d{2})/$1-$2-$3T$4:$5:$6/;
                 $date_string =~ s/00T/01T/;
             }
         }
-        return DateTime::Format::DateParse->parse_datetime( $date_string,
-            $tz->name() );
+
+        $dt = eval {
+            DateTime::Format::DateParse->parse_datetime( $date_string,
+                $tz->name() );
+        };
+        if ($@) {
+            $tz = DateTime::TimeZone->new( name => 'floating' );
+            $dt = DateTime::Format::DateParse->parse_datetime( $date_string,
+                $tz->name() );
+        }
+    } else {
+        $dt = DateTime->now( time_zone => $tz );
     }
-    return DateTime->now( time_zone => $tz );
+
+    return $dt;
 
 }
 
diff --git a/Koha/Template/Plugin/KohaDates.pm b/Koha/Template/Plugin/KohaDates.pm
index b4c1d8d..711255a 100644
--- a/Koha/Template/Plugin/KohaDates.pm
+++ b/Koha/Template/Plugin/KohaDates.pm
@@ -30,8 +30,7 @@ sub filter {
     return "" unless $text;
     $config->{with_hours} //= 0;
 
-    my $tz = DateTime::TimeZone->new(name => 'floating') unless $config->{with_hours};
-    my $dt = dt_from_string( $text, 'iso', $tz );
+    my $dt = dt_from_string( $text, 'iso' );
 
     return $config->{as_due_date} ?
         output_pref({ dt => $dt, as_due_date => 1 }) :
diff --git a/t/DateUtils.t b/t/DateUtils.t
index 6030e68..8cddce2 100755
--- a/t/DateUtils.t
+++ b/t/DateUtils.t
@@ -3,7 +3,7 @@ use DateTime;
 use DateTime::TimeZone;
 
 use C4::Context;
-use Test::More tests => 42;
+use Test::More tests => 44;
 use Test::MockModule;
 use Time::HiRes qw/ gettimeofday /;
 
@@ -162,3 +162,23 @@ cmp_ok $date_string, 'eq', '12/11/2013 06:35 PM', 'as_due_date with hours and ti
 
 my $now = DateTime->now;
 is( dt_from_string, $now, "Without parameter, dt_from_string should return today" );
+
+$module_context->mock(
+    'tz',
+    sub {
+        return DateTime::TimeZone->new( name => 'Europe/Lisbon' );
+    }
+);
+
+$dt = dt_from_string('1979-04-01');
+isa_ok( $dt, 'DateTime', 'dt_from_string should return a DateTime object if a DST is given' );
+
+$module_context->mock(
+    'tz',
+    sub {
+        return DateTime::TimeZone->new( name => 'Europe/Paris' );
+    }
+);
+
+$dt = dt_from_string('2014-03-30 02:00:00');
+isa_ok( $dt, 'DateTime', 'dt_from_string should return a DateTime object if a DST is given' );
diff --git a/t/db_dependent/Koha_template_plugin_KohaDates.t b/t/db_dependent/Koha_template_plugin_KohaDates.t
index f9a0e72..e45427e 100644
--- a/t/db_dependent/Koha_template_plugin_KohaDates.t
+++ b/t/db_dependent/Koha_template_plugin_KohaDates.t
@@ -1,16 +1,17 @@
 #!/usr/bin/perl
-#
 
-use strict;
-use warnings;
+use Modern::Perl;
 use C4::Context;
 use C4::Dates;
-use Test::More tests => 5;
+use Test::More tests => 7;
+use Test::MockModule;
 
 BEGIN {
         use_ok('Koha::Template::Plugin::KohaDates');
 }
 
+my $module_context = new Test::MockModule('C4::Context');
+
 my $date = "1973-05-21";
 my $context = C4::Context->new();
 my $dateobj = C4::Dates->new();
@@ -18,7 +19,6 @@ my $dateobj = C4::Dates->new();
 my $filter = Koha::Template::Plugin::KohaDates->new();
 ok ($filter, "new()");
 
-
 $context->set_preference( "dateformat", 'iso' );
 $context->clear_syspref_cache();
 $dateobj->reset_prefformat;
@@ -40,3 +40,23 @@ $dateobj->reset_prefformat;
 
 $filtered_date = $filter->filter($date);
 is ($filtered_date,'21/05/1973', "metric conversion") or diag ("metric conversion fails $filtered_date");
+
+$module_context->mock(
+    'tz',
+    sub {
+        return DateTime::TimeZone->new( name => 'Europe/Lisbon' );
+    }
+);
+
+$filtered_date = $filter->filter('1979-04-01');
+is( $filtered_date, '01/04/1979', 'us: dt_from_string should return the valid date if a DST is given' );
+
+$module_context->mock(
+    'tz',
+    sub {
+        return DateTime::TimeZone->new( name => 'Europe/Paris' );
+    }
+);
+
+$filtered_date = $filter->filter('2014-03-30 02:00:00');
+is( $filtered_date, '30/03/2014', 'us: dt_from_string should return a DateTime object if a DST is given' );
-- 
1.7.2.5