[open-ils-commits] [GIT] Evergreen ILS branch master updated. 6c0e0d5efaa90dd22468127d6e7d5bf87bdff6c1

Evergreen Git git at git.evergreen-ils.org
Mon Sep 24 14:43:03 EDT 2018


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Evergreen ILS".

The branch, master has been updated
       via  6c0e0d5efaa90dd22468127d6e7d5bf87bdff6c1 (commit)
       via  110624bac23fcd0e53fef11d2af091c942e6d9aa (commit)
       via  867da55cd97a0973b20ce0df26a6f4edfa7645eb (commit)
       via  6fbbcca096402e099f90702e5f79a98b80bc69a2 (commit)
       via  b1c3b925764f6d8bf7cfe8b9f9c9a4ebe4c09d04 (commit)
       via  401fb4cc1a5a065d0b82692dae4f64a449d820f7 (commit)
       via  8fa7940b570fbb22c478e31735959ce88fdce30d (commit)
      from  72152af78b20dee043b865f4471c0e066538e1a6 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 6c0e0d5efaa90dd22468127d6e7d5bf87bdff6c1
Author: Galen Charlton <gmc at equinoxinitiative.org>
Date:   Mon Sep 24 13:56:09 2018 -0400

    LP#1789442: turn of Perl taint-checking on 14-OpenILS-Utils.t
    
    This works around a bug in DateTime::TimeZone 1.63
    <https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=737265> that
    causes one of the new tests to spuriously fail on Ubuntu 14.04 LTS.
    
    As the comment indicates, taint checking is not typically enabled
    when running Evergreen, but we may want to consider changing
    that should tuits arise.
    
    Signed-off-by: Galen Charlton <gmc at equinoxinitiative.org>
    Signed-off-by: Kathy Lussier <klussier at masslnc.org>

diff --git a/Open-ILS/src/perlmods/t/14-OpenILS-Utils.t b/Open-ILS/src/perlmods/t/14-OpenILS-Utils.t
index a341f3e..636d2ab 100644
--- a/Open-ILS/src/perlmods/t/14-OpenILS-Utils.t
+++ b/Open-ILS/src/perlmods/t/14-OpenILS-Utils.t
@@ -1,4 +1,18 @@
-#!perl -T
+#!perl
+
+# FIXME: unlike the rest of the test cases here, we're /not/ enabling
+# taint checks. The version of DateTime::TimeZone that ships with
+# Ubuntu 14.04 LTS (Trusty) has a bug where attempting to get the
+# local time zone can fail (https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=737265).
+#
+# It's arguable whether taint checking should be enabled at all in
+# the test suite. On the one hand, it is recommended practice for
+# all code that accepts external input; on the other hand, a typical
+# Evergreen installation doesn't run anything setuid/setgid that
+# would automatically trigger taint-checking. Ideally we would
+# eat our Wheaties, but we may be looking at consuming an entire
+# truckload to verify that everything would continue to work if
+# we turn it on across the board.
 
 use Test::More tests => 43;
 use Test::Warn;

commit 110624bac23fcd0e53fef11d2af091c942e6d9aa
Author: Galen Charlton <gmc at equinoxinitiative.org>
Date:   Mon Sep 24 13:55:39 2018 -0400

    LP#1789442: restore column allocation for barcode input
    
    Signed-off-by: Galen Charlton <gmc at equinoxinitiative.org>
    Signed-off-by: Kathy Lussier <klussier at masslnc.org>

diff --git a/Open-ILS/src/templates/staff/circ/patron/t_checkout.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_checkout.tt2
index fd56e02..d4fce7c 100644
--- a/Open-ILS/src/templates/staff/circ/patron/t_checkout.tt2
+++ b/Open-ILS/src/templates/staff/circ/patron/t_checkout.tt2
@@ -1,7 +1,7 @@
 <!-- item checkout form / list -->
 
 <div class="row pad-vert">
-  <div class="col-md-5">
+  <div class="col-md-6">
     <form ng-submit="checkout(checkoutArgs)" role="form" class="form-inline">
       <div class="input-group">
 

commit 867da55cd97a0973b20ce0df26a6f4edfa7645eb
Author: Galen Charlton <gmc at equinoxinitiative.org>
Date:   Fri Sep 21 15:23:11 2018 -0400

    LP#1789442: fix editing due date of hourly loans in web staff
    
    This patch fixes a bug where editing the due date of an hourly
    loan would result in the time portion always getting set to 00:00.
    
    To test
    -------
    [1] Set up some daily and hourly loans in your database.
    [2] Apply the patch.
    [3] From the items out page, edit the due date for one or
        more hourly loans. Verify that the resulting due date
        is set correctly.
    [4] From the items out page, edit the due date for some
        daily loans and verify correctness. In particular,
        verify that the resulting due date is /not/ the
        following day if testing in time zones in the Americas.
    
    Signed-off-by: Galen Charlton <gmc at equinoxinitiative.org>
    Signed-off-by: Kathy Lussier <klussier at masslnc.org>

diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ.pm
index f1fcf1f..bad3be3 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ.pm
@@ -685,6 +685,11 @@ sub set_circ_due_date {
     if (!(interval_to_seconds($circ->duration) % 86400)) { # duration is divisible by days
         my $original_date = DateTime::Format::ISO8601->new->parse_datetime(clean_ISO8601($circ->due_date));
         my $new_date = DateTime::Format::ISO8601->new->parse_datetime($date);
+
+        # since the new date may be coming in as UTC, convert it
+        # to the same time zone as the original due date so that
+        # ->ymd is more likely to yield the expected results
+        $new_date->set_time_zone($original_date->time_zone());
         $date = clean_ISO8601( $new_date->ymd . 'T' . $original_date->strftime('%T%z') );
     }
 
diff --git a/Open-ILS/web/js/ui/default/staff/circ/patron/items_out.js b/Open-ILS/web/js/ui/default/staff/circ/patron/items_out.js
index 105c9f5..e75d9a2 100644
--- a/Open-ILS/web/js/ui/default/staff/circ/patron/items_out.js
+++ b/Open-ILS/web/js/ui/default/staff/circ/patron/items_out.js
@@ -320,13 +320,7 @@ function($scope , $q , $routeParams , $timeout , egCore , egUser , patronSvc ,
                     // Fire off the due-date updater for each circ.
                     // When all is done, close the dialog
                     $scope.ok = function(args) {
-                        // toISOString gives us Zulu time, so
-                        // adjust for that before truncating to date
-                        var adjust_date = new Date( $scope.args.due_date );
-                        adjust_date.setMinutes(
-                            $scope.args.due_date.getMinutes() - adjust_date.getTimezoneOffset()
-                        );
-                        var due = adjust_date.toISOString().replace(/T.*/,'');
+                        var due = $scope.args.due_date.toISOString();
                         console.debug("applying due date of " + due);
 
                         var promises = [];

commit 6fbbcca096402e099f90702e5f79a98b80bc69a2
Author: Galen Charlton <gmc at equinoxinitiative.org>
Date:   Fri Sep 21 14:58:47 2018 -0400

    LP#1552778: add timepicker to webstaff checkout page
    
    This patch adds a timepicker to go along with the datepicker
    if the operator invokes the option to set a specific due
    date.
    
    To test
    -------
    [1] Arrange circ policies to have both hourly and daily loans.
    [2] Apply the patch.
    [3] Check out an item for an hourly loan. Verify that the
        due date and time is per policy.
    [4] Check out an item for a daily loan. Verify that the
        due date is per policy.
    [5] Check out an item for an hourly loan, but set a specific
        due date and time. Verify that the due date and time matches
        the selected value.
    [6] Check out an item for a daily loan, but set a specific
        due date. Verify that the due date matches the selected
        value; note that any time component is ignored since
        for daily loans the time gets normalized to 23:59.
    
    Signed-off-by: Galen Charlton <gmc at equinoxinitiative.org>
    Signed-off-by: Kathy Lussier <klussier at masslnc.org>

diff --git a/Open-ILS/src/templates/staff/circ/patron/t_checkout.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_checkout.tt2
index 1db71f1..fd56e02 100644
--- a/Open-ILS/src/templates/staff/circ/patron/t_checkout.tt2
+++ b/Open-ILS/src/templates/staff/circ/patron/t_checkout.tt2
@@ -1,7 +1,7 @@
 <!-- item checkout form / list -->
 
 <div class="row pad-vert">
-  <div class="col-md-6">
+  <div class="col-md-5">
     <form ng-submit="checkout(checkoutArgs)" role="form" class="form-inline">
       <div class="input-group">
 
@@ -39,8 +39,8 @@
     <div class="flex-row">
       <div class="flex-cell"></div>
 
-<div class="input-group">
-<div class="input-group-btn" uib-dropdown>
+<div class="form-group row">
+<div class="col-md-3" uib-dropdown>
       <button type="button" ng-class="{'btn-success' : date_options.has_sticky_date}" class="btn btn-default" uib-dropdown-toggle>
         [% l('Date Options') %]
         <span class="caret"></span>
@@ -75,10 +75,8 @@
           [% l('Specific Due Date') %]
         </label>
       </div> -->
-      <!-- FIXME: This needs a time component as well, but type="datetime" 
-            is not yet supported by any browsers -->
-      <div>
-        <eg-date-input ng-model="checkoutArgs.due_date" ng-disabled="!date_options.has_sticky_date"></eg-date-input>
+      <div class="col-md-4">
+        <eg-date-input ng-model="checkoutArgs.due_date" ng-disabled="!date_options.has_sticky_date" show-time-picker></eg-date-input>
       </div>
 </div>
     </div>

commit b1c3b925764f6d8bf7cfe8b9f9c9a4ebe4c09d04
Author: Galen Charlton <gmc at equinoxinitiative.org>
Date:   Fri Sep 21 14:30:01 2018 -0400

    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 <gmc at equinoxinitiative.org>
    Signed-off-by: Kathy Lussier <klussier at masslnc.org>

diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Utils/DateTime.pm b/Open-ILS/src/perlmods/lib/OpenILS/Utils/DateTime.pm
index 69fec7a..05f0883 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 ec164a7..a341f3e 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');

commit 401fb4cc1a5a065d0b82692dae4f64a449d820f7
Author: Galen Charlton <gmc at equinoxinitiative.org>
Date:   Fri Sep 21 14:04:24 2018 -0400

    LP#1552778: add perldoc and unit tests for clean_ISO8601
    
    To test
    -------
    [1] Apply patch.
    [2] Verify new tests in t/14-OpenILS-Utils.t pass.
    
    Signed-off-by: Galen Charlton <gmc at equinoxinitiative.org>
    Signed-off-by: Kathy Lussier <klussier at masslnc.org>

diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Utils/DateTime.pm b/Open-ILS/src/perlmods/lib/OpenILS/Utils/DateTime.pm
index d622480..69fec7a 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Utils/DateTime.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Utils/DateTime.pm
@@ -206,6 +206,41 @@ sub gmtime_ISO8601 {
 	return sprintf('%d-%0.2d-%0.2dT%0.2d:%0.2d:%0.2d+00:00', $y, $M, $d, $h, $m, $s);
 }
 
+=head2 clean_ISO8601($date_string)
+
+Given a date string or a date/time string in a variety of ad-hoc
+formats, returns an ISO8601-formatted date/time string.
+
+The date portion of the input is expected to consist of a four-digit
+year, followed by a two-digit month, followed by a two-digit year,
+with each part optionally separated by a hyphen.  If there is
+only a date portion, it will be normalized to use hyphens.
+
+If there is no time portion in the input, "T00:00:00" is appended
+before the results are returned.
+
+For example, "20180917" would become "2018-09-17T00:00:00".
+
+If the input does not have a recognizable date, it is simply
+returned as is.
+
+If there is a time portion, it is expected to consist of two-digit
+hour, minutes, and seconds delimited by colons.  That time is
+appended to the return with "T" separting the date and time
+portions.
+
+If there is an ISO8601-style numeric timezone offset, it is
+normalized and appended to the return. If there is no timezone
+offset supplied in the input, the offset of the server's
+time zone is append to the return. Note that as implied above,
+if only a date is supplied, the return value does not include a
+timezone offset.
+
+For example, for a server running in U.S. Eastern Daylight
+Savings time, "20180917 08:31:15" would become "2018-09-17T08:31:15-04:00".
+
+=cut
+
 sub clean_ISO8601 {
 	my $self = shift;
 	my $date = shift || $self;
diff --git a/Open-ILS/src/perlmods/t/14-OpenILS-Utils.t b/Open-ILS/src/perlmods/t/14-OpenILS-Utils.t
index dc6e2a1..ec164a7 100644
--- a/Open-ILS/src/perlmods/t/14-OpenILS-Utils.t
+++ b/Open-ILS/src/perlmods/t/14-OpenILS-Utils.t
@@ -1,7 +1,9 @@
 #!perl -T
 
-use Test::More tests => 39;
+use Test::More tests => 42;
 use Test::Warn;
+use DateTime::TimeZone;
+use DateTime::Format::ISO8601;
 use utf8;
 
 use_ok( 'OpenILS::Utils::Configure' );
@@ -107,3 +109,15 @@ is (OpenILS::Utils::DateTime::interval_to_seconds('1 week'), 604800);
 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/;
+
+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');
+is (OpenILS::Utils::DateTime::clean_ISO8601('20180917 08:31:15'), "2018-09-17T08:31:15$offset", 'time zone added to date/time');

commit 8fa7940b570fbb22c478e31735959ce88fdce30d
Author: Galen Charlton <gmc at equinoxinitiative.org>
Date:   Fri Sep 21 11:00:25 2018 -0400

    LP#1552778: copy some date/time utils from OpenSRF
    
    As preparation for subsequent bugfixes, this patch
    copies several date/time routines from OpenSRF::Utils
    to a new module, OpenILS::Utils::DateTime. Specifically,
    the routines copied over are:
    
    * clean_ISO8601() (renaming of the OpenSRF cleanse_ISO8601)
    * gmtime_ISO8601()
    * interval_to_seconds()
    * seconds_to_interval()
    
    This move will allow us to fix bugs in this core routines
    without requiring a mandatory OpenSRF upgrade. Furthermore,
    with the exception of interval_to_seconds() (and in only one
    place), none of those routines are used by OpenSRF itself.
    
    To test
    -------
    [1] Apply the patch.
    [2] Verify that unit tests pass.
    [3] Verify that all Perl services start correctly.
    [4] Verify that date/time and interval calculations continue
        to work as expected, particularly in circulation.
    
    Signed-off-by: Galen Charlton <gmc at equinoxinitiative.org>
    Signed-off-by: Kathy Lussier <klussier at masslnc.org>

diff --git a/Open-ILS/src/offline/offline.pl b/Open-ILS/src/offline/offline.pl
index 4bc9e51..ae97227 100755
--- a/Open-ILS/src/offline/offline.pl
+++ b/Open-ILS/src/offline/offline.pl
@@ -10,7 +10,8 @@ use OpenSRF::EX qw/:try/;
 use Data::Dumper;
 use OpenILS::Utils::Fieldmapper;
 use Digest::MD5 qw/md5_hex/;
-use OpenSRF::Utils qw/:daemon cleanse_ISO8601/;
+use OpenSRF::Utils qw/:daemon/;
+use OpenILS::Utils::DateTime qw/clean_ISO8601/;
 use OpenILS::Utils::OfflineStore;
 use OpenSRF::Utils::SettingsClient;
 use OpenSRF::Utils;
@@ -723,7 +724,7 @@ sub ol_handle_checkout {
             && ! $seen_barcode{$barcode}
         ) {
             $seen_barcode{$barcode} = 1;
-            my $cts = DateTime::Format::ISO8601->parse_datetime( cleanse_ISO8601($c->status_changed_time()) )->epoch();
+            my $cts = DateTime::Format::ISO8601->parse_datetime( clean_ISO8601($c->status_changed_time()) )->epoch();
             my $xts = $command->{timestamp}; # Transaction Time Stamp
             $logger->activity("offline: ol_handle_checkout: considering status_changed_time for barcode=$barcode, cts=$cts, xts=$xts");
 
@@ -786,7 +787,7 @@ sub ol_handle_renew {
             && ! $seen_barcode{$barcode}
         ) {
             $seen_barcode{$barcode} = 1;
-            my $cts = DateTime::Format::ISO8601->parse_datetime( cleanse_ISO8601($c->status_changed_time()) )->epoch();
+            my $cts = DateTime::Format::ISO8601->parse_datetime( clean_ISO8601($c->status_changed_time()) )->epoch();
             my $xts = $command->{timestamp}; # Transaction Time Stamp
             $logger->activity("offline: ol_handle_renew: considering status_changed_time for barcode=$barcode, cts=$cts, xts=$xts");
 
@@ -843,7 +844,7 @@ sub ol_handle_checkin {
             && ! $seen_barcode{$barcode}
         ) {
             $seen_barcode{$barcode} = 1;
-            my $cts = DateTime::Format::ISO8601->parse_datetime( cleanse_ISO8601($c->status_changed_time()) )->epoch();
+            my $cts = DateTime::Format::ISO8601->parse_datetime( clean_ISO8601($c->status_changed_time()) )->epoch();
             my $xts = $command->{timestamp}; # Transaction Time Stamp
             $logger->activity("offline: ol_handle_checkin: considering status_changed_time for barcode=$barcode, cts=$cts, xts=$xts");
 
@@ -982,7 +983,7 @@ sub ol_handle_register {
     # calculate the expire date for the patron based on the profile group
     my ($grp) = grep {$_->id == $actor->profile} @$user_groups;
     if($grp) {
-        my $seconds = OpenSRF::Utils->interval_to_seconds($grp->perm_interval);
+        my $seconds = OpenILS::Utils::DateTime->interval_to_seconds($grp->perm_interval);
         my $expire_date = DateTime->from_epoch(epoch => DateTime->now->epoch + $seconds)->epoch;
 		$logger->debug("offline: setting expire date to $expire_date");
         $actor->expire_date($U->epoch2ISO8601($expire_date));
diff --git a/Open-ILS/src/perlmods/MANIFEST b/Open-ILS/src/perlmods/MANIFEST
index 8473b19..8e7b0f5 100644
--- a/Open-ILS/src/perlmods/MANIFEST
+++ b/Open-ILS/src/perlmods/MANIFEST
@@ -136,6 +136,7 @@ lib/OpenILS/Utils/Configure.pm
 lib/OpenILS/Utils/Cronscript.pm
 lib/OpenILS/Utils/Cronscript.pm.in
 lib/OpenILS/Utils/CStoreEditor.pm
+lib/OpenILS/Utils/DateTime.pm
 lib/OpenILS/Utils/Fieldmapper.pm
 lib/OpenILS/Utils/HTTPClient.pm
 lib/OpenILS/Utils/ISBN.pm
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm
index 662241c..31e7083 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm
@@ -16,7 +16,7 @@ use OpenILS::Application::AppUtils;
 use OpenILS::Utils::Fieldmapper;
 use OpenILS::Utils::ModsParser;
 use OpenSRF::Utils::Logger qw/$logger/;
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
 use OpenSRF::Utils::SettingsClient;
 
 use OpenSRF::Utils::Cache;
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor/ClosedDates.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor/ClosedDates.pm
index bc87abe..fc53c16 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor/ClosedDates.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor/ClosedDates.pm
@@ -2,7 +2,7 @@ package OpenILS::Application::Actor::ClosedDates;
 use base 'OpenILS::Application';
 use strict; use warnings;
 use OpenSRF::EX qw(:try);
-use OpenSRF::Utils qw(:datetime);
+use OpenILS::Utils::DateTime qw(:datetime);
 use DateTime;
 use DateTime::Format::ISO8601;
 use OpenILS::Utils::CStoreEditor q/:funcs/;
@@ -302,7 +302,7 @@ sub is_probably_emergency_closing {
 
     # First, when is it?
     my $start_seconds = DateTime::Format::ISO8601->parse_datetime(
-        cleanse_ISO8601($date->close_start)
+        clean_ISO8601($date->close_start)
     )->epoch;
 
     # Is it in the past?
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Booking.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Booking.pm
index 3727011..d7ea212 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Booking.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Booking.pm
@@ -7,7 +7,7 @@ use POSIX qw/strftime/;
 use OpenILS::Application;
 use base qw/OpenILS::Application/;
 
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
 use OpenILS::Utils::CStoreEditor qw/:funcs/;
 use OpenILS::Utils::Fieldmapper;
 use OpenILS::Application::AppUtils;
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ.pm
index 2c987d9..f1fcf1f 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ.pm
@@ -20,7 +20,7 @@ use DateTime::Format::ISO8601;
 
 use OpenILS::Application::AppUtils;
 
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
 use OpenSRF::AppSession;
 use OpenILS::Utils::ModsParser;
 use OpenILS::Event;
@@ -488,14 +488,14 @@ sub set_circ_claims_returned {
     $circ->stop_fines_time('now') unless $circ->stop_fines_time;
 
     if( $backdate ) {
-        $backdate = cleanse_ISO8601($backdate);
+        $backdate = clean_ISO8601($backdate);
 
-        my $original_date = DateTime::Format::ISO8601->new->parse_datetime(cleanse_ISO8601($circ->due_date));
+        my $original_date = DateTime::Format::ISO8601->new->parse_datetime(clean_ISO8601($circ->due_date));
         my $new_date = DateTime::Format::ISO8601->new->parse_datetime($backdate);
         $backdate = $new_date->ymd . 'T' . $original_date->strftime('%T%z');
 
         # clean it up once again; need a : in the timezone offset. E.g. -06:00 not -0600
-        $backdate = cleanse_ISO8601($backdate);
+        $backdate = clean_ISO8601($backdate);
 
         # make it look like the circ stopped at the cliams returned time
         $circ->stop_fines_time($backdate);
@@ -642,8 +642,8 @@ sub post_checkin_backdate_circ_impl {
         $backdate and $circ->checkin_time;
 
     # update the checkin and stop_fines times to reflect the new backdate
-    $circ->stop_fines_time(cleanse_ISO8601($backdate));
-    $circ->checkin_time(cleanse_ISO8601($backdate));
+    $circ->stop_fines_time(clean_ISO8601($backdate));
+    $circ->checkin_time(clean_ISO8601($backdate));
     $e->update_action_circulation($circ) or return $e->die_event;
 
     # now void the overdues "erased" by the back-dating
@@ -680,12 +680,12 @@ sub set_circ_due_date {
         or return $e->die_event;
 
     return $e->die_event unless $e->allowed('CIRC_OVERRIDE_DUE_DATE', $circ->circ_lib);
-    $date = cleanse_ISO8601($date);
+    $date = clean_ISO8601($date);
 
     if (!(interval_to_seconds($circ->duration) % 86400)) { # duration is divisible by days
-        my $original_date = DateTime::Format::ISO8601->new->parse_datetime(cleanse_ISO8601($circ->due_date));
+        my $original_date = DateTime::Format::ISO8601->new->parse_datetime(clean_ISO8601($circ->due_date));
         my $new_date = DateTime::Format::ISO8601->new->parse_datetime($date);
-        $date = cleanse_ISO8601( $new_date->ymd . 'T' . $original_date->strftime('%T%z') );
+        $date = clean_ISO8601( $new_date->ymd . 'T' . $original_date->strftime('%T%z') );
     }
 
     $circ->due_date($date);
@@ -743,7 +743,7 @@ sub create_in_house_use {
     }
 
     if( $use_time ne 'now' ) {
-        $use_time = cleanse_ISO8601($use_time);
+        $use_time = clean_ISO8601($use_time);
         $logger->debug("in_house_use setting use time to $use_time");
     }
 
@@ -1590,7 +1590,7 @@ sub mark_item_missing_pieces {
 
                 $logger->info('open-ils.circ.mark_item_missing_pieces: item needed for hold, shortening due date');
                 my $due_date = DateTime->now(time_zone => 'local');
-                $co_params->{'due_date'} = cleanse_ISO8601( $due_date->strftime('%FT%T%z') );
+                $co_params->{'due_date'} = clean_ISO8601( $due_date->strftime('%FT%T%z') );
             } else {
                 $logger->info('open-ils.circ.mark_item_missing_pieces: item not needed for hold');
             }
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/CircCommon.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/CircCommon.pm
index 879644f..3b6bfe9 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/CircCommon.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/CircCommon.pm
@@ -3,7 +3,7 @@ use strict; use warnings;
 use DateTime;
 use DateTime::Format::ISO8601;
 use OpenILS::Application::AppUtils;
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
 use OpenILS::Event;
 use OpenSRF::Utils::Logger qw(:logger);
 use OpenILS::Utils::CStoreEditor q/:funcs/;
@@ -50,11 +50,11 @@ sub void_or_zero_overdues {
         # turn it into an interval that interval_to_seconds can parse
         my $duration = $circ->fine_interval;
         $duration =~ s/(\d{2}):(\d{2}):(\d{2})/$1 h $2 m $3 s/o;
-        my $interval = OpenSRF::Utils->interval_to_seconds($duration);
+        my $interval = OpenILS::Utils::DateTime->interval_to_seconds($duration);
 
-        my $date = DateTime::Format::ISO8601->parse_datetime(cleanse_ISO8601($backdate));
-        my $due_date = DateTime::Format::ISO8601->parse_datetime(cleanse_ISO8601($circ->due_date))->epoch;
-        my $grace_period = extend_grace_period( $class, $circ->circ_lib, $circ->due_date, OpenSRF::Utils->interval_to_seconds($circ->grace_period), $e);
+        my $date = DateTime::Format::ISO8601->parse_datetime(clean_ISO8601($backdate));
+        my $due_date = DateTime::Format::ISO8601->parse_datetime(clean_ISO8601($circ->due_date))->epoch;
+        my $grace_period = extend_grace_period( $class, $circ->circ_lib, $circ->due_date, OpenILS::Utils::DateTime->interval_to_seconds($circ->grace_period), $e);
         if($date->epoch <= $due_date + $grace_period) {
             $logger->info("backdate $backdate is within grace period, voiding all");
         } else {
@@ -223,7 +223,7 @@ sub extend_grace_period {
     my($class, $circ_lib, $due_date, $grace_period, $e, $h) = @_;
     if ($grace_period >= 86400) { # Only extend grace periods greater than or equal to a full day
         my $parser = DateTime::Format::ISO8601->new;
-        my $due_dt = $parser->parse_datetime( cleanse_ISO8601( $due_date ) );
+        my $due_dt = $parser->parse_datetime( clean_ISO8601( $due_date ) );
         my $due = $due_dt->epoch;
 
         my $grace_extend = $U->ou_ancestor_setting_value($circ_lib, 'circ.grace.extend');
@@ -293,7 +293,7 @@ sub extend_grace_period {
                         if ($cl and @$cl) {
                             $closed = 1;
                             foreach (@$cl) {
-                                my $cl_dt = $parser->parse_datetime( cleanse_ISO8601( $_->close_end ) );
+                                my $cl_dt = $parser->parse_datetime( clean_ISO8601( $_->close_end ) );
                                 while ($due_dt <= $cl_dt) {
                                     $due_dt->add( seconds => 86400 );
                                     $new_grace_period += 86400;
@@ -493,7 +493,7 @@ sub generate_fines {
             # each (ils) transaction is processed in its own (db) transaction
             $e->xact_begin if $commit;
 
-            my $due_dt = $parser->parse_datetime( cleanse_ISO8601( $c->$due_date_method ) );
+            my $due_dt = $parser->parse_datetime( clean_ISO8601( $c->$due_date_method ) );
     
             my $due = $due_dt->epoch;
             my $now = time;
@@ -541,8 +541,8 @@ sub generate_fines {
     
             my $last_fine;
             if ($fine) {
-                $conn->respond( "Last billing time: ".$fine->billing_ts." (clensed format: ".cleanse_ISO8601( $fine->billing_ts ).")") if $conn;
-                $last_fine = $parser->parse_datetime( cleanse_ISO8601( $fine->billing_ts ) )->epoch;
+                $conn->respond( "Last billing time: ".$fine->billing_ts." (clensed format: ".clean_ISO8601( $fine->billing_ts ).")") if $conn;
+                $last_fine = $parser->parse_datetime( clean_ISO8601( $fine->billing_ts ) )->epoch;
             } else {
                 $logger->info( "Potential first billing for circ ".$c->id );
                 $last_fine = $due;
@@ -1051,7 +1051,7 @@ sub _has_refundable_payments {
 
     if ($last_payment->[0]) {
         my $interval_secs = interval_to_seconds($interval);
-        my $payment_ts = DateTime::Format::ISO8601->parse_datetime(cleanse_ISO8601($last_payment->[0]->payment_ts))->epoch;
+        my $payment_ts = DateTime::Format::ISO8601->parse_datetime(clean_ISO8601($last_payment->[0]->payment_ts))->epoch;
         my $now = time;
         return 1 if ($payment_ts + $interval_secs >= $now);
     }
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm
index 6f5433a..bf5dd0e 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Circulate.pm
@@ -391,7 +391,7 @@ use OpenSRF::Utils::Cache;
 use Digest::MD5 qw(md5_hex);
 use DateTime::Format::ISO8601;
 use OpenILS::Utils::PermitHold;
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
 use OpenSRF::Utils::SettingsClient;
 use OpenILS::Application::Circ::Holds;
 use OpenILS::Application::Circ::Transit;
@@ -1021,7 +1021,7 @@ sub mk_env {
             unless $U->is_true($patron->card->active);
     
         my $expire = DateTime::Format::ISO8601->new->parse_datetime(
-            cleanse_ISO8601($patron->expire_date));
+            clean_ISO8601($patron->expire_date));
     
         $self->bail_on_events(OpenILS::Event->new('PATRON_ACCOUNT_EXPIRED'))
             if( CORE::time > $expire->epoch ) ;
@@ -1200,8 +1200,8 @@ sub do_copy_checks {
                 );
 
                 if($auto_renew_intvl) {
-                    my $intvl_seconds = OpenSRF::Utils->interval_to_seconds($auto_renew_intvl);
-                    my $checkout_time = DateTime::Format::ISO8601->new->parse_datetime( cleanse_ISO8601($old_circ->xact_start) );
+                    my $intvl_seconds = OpenILS::Utils::DateTime->interval_to_seconds($auto_renew_intvl);
+                    my $checkout_time = DateTime::Format::ISO8601->new->parse_datetime( clean_ISO8601($old_circ->xact_start) );
 
                     if(DateTime->now > $checkout_time->add(seconds => $intvl_seconds)) {
                         $payload->{auto_renew} = 1;
@@ -2167,7 +2167,7 @@ sub build_checkout_circ_object {
     # if the user provided an overiding checkout time,
     # (e.g. the checkout really happened several hours ago), then
     # we apply that here.  Does this need a perm??
-    $circ->xact_start(cleanse_ISO8601($self->checkout_time))
+    $circ->xact_start(clean_ISO8601($self->checkout_time))
         if $self->checkout_time;
 
     # if a patron is renewing, 'requestor' will be the patron
@@ -2267,7 +2267,7 @@ sub booking_adjusted_due_date {
         return $self->bail_on_events($self->editor->event)
             unless $self->editor->allowed('CIRC_OVERRIDE_DUE_DATE', $self->circ_lib);
 
-       $circ->due_date(cleanse_ISO8601($self->due_date));
+       $circ->due_date(clean_ISO8601($self->due_date));
 
     } else {
 
@@ -2297,14 +2297,14 @@ sub booking_adjusted_due_date {
         return $self->bail_on_events($bookings) if ref($bookings) eq 'HASH';
         
         my $dt_parser = DateTime::Format::ISO8601->new;
-        my $due_date = $dt_parser->parse_datetime( cleanse_ISO8601($circ->due_date) );
+        my $due_date = $dt_parser->parse_datetime( clean_ISO8601($circ->due_date) );
 
         for my $bid (@$bookings) {
 
             my $booking = $self->editor->retrieve_booking_reservation( $bid );
 
-            my $booking_start = $dt_parser->parse_datetime( cleanse_ISO8601($booking->start_time) );
-            my $booking_end = $dt_parser->parse_datetime( cleanse_ISO8601($booking->end_time) );
+            my $booking_start = $dt_parser->parse_datetime( clean_ISO8601($booking->start_time) );
+            my $booking_end = $dt_parser->parse_datetime( clean_ISO8601($booking->end_time) );
 
             return $self->bail_on_events( OpenILS::Event->new('COPY_RESERVED') )
                 if ($booking_start < DateTime->now);
@@ -2325,7 +2325,7 @@ sub booking_adjusted_due_date {
             $new_circ_duration++ if $new_circ_duration % 86400 == 0;
             $circ->duration("$new_circ_duration seconds");
 
-            $circ->due_date(cleanse_ISO8601($due_date->strftime('%FT%T%z')));
+            $circ->due_date(clean_ISO8601($due_date->strftime('%FT%T%z')));
             $changed = 1;
         }
 
@@ -2347,7 +2347,7 @@ sub apply_modified_due_date {
         return $self->bail_on_events($self->editor->event)
             unless $self->editor->allowed('CIRC_OVERRIDE_DUE_DATE', $self->circ_lib);
 
-      $circ->due_date(cleanse_ISO8601($self->due_date));
+      $circ->due_date(clean_ISO8601($self->due_date));
 
    } else {
 
@@ -2393,13 +2393,13 @@ sub create_due_date {
 
     # for now, use the server timezone.  TODO: use workstation org timezone
     my $due_date = DateTime->now(time_zone => 'local');
-    $due_date = DateTime::Format::ISO8601->new->parse_datetime(cleanse_ISO8601($start_time)) if $start_time;
+    $due_date = DateTime::Format::ISO8601->new->parse_datetime(clean_ISO8601($start_time)) if $start_time;
 
     # add the circ duration
-    $due_date->add(seconds => OpenSRF::Utils->interval_to_seconds($duration));
+    $due_date->add(seconds => OpenILS::Utils::DateTime->interval_to_seconds($duration));
 
     if($date_ceiling) {
-        my $cdate = DateTime::Format::ISO8601->new->parse_datetime(cleanse_ISO8601($date_ceiling));
+        my $cdate = DateTime::Format::ISO8601->new->parse_datetime(clean_ISO8601($date_ceiling));
         if ($cdate > DateTime->now and ($cdate < $due_date or $U->is_true( $force_date ))) {
             $logger->info("circulator: overriding due date with date ceiling: $date_ceiling");
             $due_date = $cdate;
@@ -2480,7 +2480,7 @@ sub checkout_noncat {
 
    my $lib      = $self->noncat_circ_lib || $self->circ_lib;
    my $count    = $self->noncat_count || 1;
-   my $cotime   = cleanse_ISO8601($self->checkout_time) || "";
+   my $cotime   = clean_ISO8601($self->checkout_time) || "";
 
    $logger->info("circulator: circ creating $count noncat circs with checkout time $cotime");
 
@@ -2525,8 +2525,8 @@ sub check_transit_checkin_interval {
     # transit from X to X for whatever reason has no min interval
     return if $self->transit->source == $self->transit->dest;
 
-    my $seconds = OpenSRF::Utils->interval_to_seconds($interval);
-    my $t_start = DateTime::Format::ISO8601->new->parse_datetime(cleanse_ISO8601($self->transit->source_send_time));
+    my $seconds = OpenILS::Utils::DateTime->interval_to_seconds($interval);
+    my $t_start = DateTime::Format::ISO8601->new->parse_datetime(clean_ISO8601($self->transit->source_send_time));
     my $horizon = $t_start->add(seconds => $seconds);
 
     # See if we are still within the transit checkin forbidden range
@@ -3568,9 +3568,9 @@ sub handle_fines {
         # If we have a grace period
         if($obj->can('grace_period')) {
             # Parse out the due date
-            my $due_date = $dt_parser->parse_datetime( cleanse_ISO8601($obj->due_date) );
+            my $due_date = $dt_parser->parse_datetime( clean_ISO8601($obj->due_date) );
             # Add the grace period to the due date
-            $due_date->add(seconds => OpenSRF::Utils->interval_to_seconds($obj->grace_period));
+            $due_date->add(seconds => OpenILS::Utils::DateTime->interval_to_seconds($obj->grace_period));
             # Don't generate fines on circs still in grace period
             $skip_for_grace = $due_date > DateTime->now;
         }
@@ -3800,7 +3800,7 @@ sub checkin_handle_lost_or_longoverdue {
             int($tm[3]), int($tm[4]), int($tm[5]), int($tm[6]));
 
         my $last_chance = 
-            OpenSRF::Utils->interval_to_seconds($max_return) + int($due);
+            OpenILS::Utils::DateTime->interval_to_seconds($max_return) + int($due);
 
         $logger->info("MAX OD: $max_return LAST ACTIVITY: ".
             "$last_activity DUEDATE: ".$circ->due_date." TODAY: $today ".
@@ -3865,8 +3865,8 @@ sub checkin_handle_backdate {
     # not the input.  Do we need to do this?  This certainly interferes with
     # backdating of hourly checkouts, but that is likely a very rare case.
     # ------------------------------------------------------------------
-    my $bd = cleanse_ISO8601($self->backdate);
-    my $original_date = DateTime::Format::ISO8601->new->parse_datetime(cleanse_ISO8601($self->circ->due_date));
+    my $bd = clean_ISO8601($self->backdate);
+    my $original_date = DateTime::Format::ISO8601->new->parse_datetime(clean_ISO8601($self->circ->due_date));
     my $new_date = DateTime::Format::ISO8601->new->parse_datetime($bd);
     $new_date->set_hour($original_date->hour());
     $new_date->set_minute($original_date->minute());
@@ -3877,7 +3877,7 @@ sub checkin_handle_backdate {
         $logger->info("circulator: ignoring future backdate: $new_date");
         delete $self->{backdate};
     } else {
-        $self->backdate(cleanse_ISO8601($new_date->datetime()));
+        $self->backdate(clean_ISO8601($new_date->datetime()));
     }
 
     return undef;
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Holds.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Holds.pm
index 457b8aa..dcbe7dd 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Holds.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Holds.pm
@@ -33,7 +33,7 @@ use OpenILS::Application::Circ::Transit;
 use OpenILS::Application::Actor::Friends;
 use DateTime;
 use DateTime::Format::ISO8601;
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
 use Digest::MD5 qw(md5_hex);
 use OpenSRF::Utils::Cache;
 use OpenSRF::Utils::JSON;
@@ -269,7 +269,7 @@ sub create_hold {
     my $expire_setting = $U->ou_ancestor_setting_value($recipient->home_ou, OILS_SETTING_BLOCK_HOLD_FOR_EXPIRED_PATRON);
     if ($expire_setting) {
         my $expire = DateTime::Format::ISO8601->new->parse_datetime(
-            cleanse_ISO8601($recipient->expire_date));
+            clean_ISO8601($recipient->expire_date));
 
         push( @events, OpenILS::Event->new(
             'PATRON_ACCOUNT_EXPIRED',
@@ -588,7 +588,7 @@ sub retrieve_holds {
         } elsif($cancel_age) { # limit by age
 
             # find all of the canceled holds that were canceled within the configured time frame
-            my $date = DateTime->now->subtract(seconds => OpenSRF::Utils::interval_to_seconds($cancel_age));
+            my $date = DateTime->now->subtract(seconds => OpenILS::Utils::DateTime->interval_to_seconds($cancel_age));
             $date = $U->epoch2ISO8601($date->epoch);
             $holds_query->{where}->{cancel_time} = {'>=' => $date};
         }
@@ -1103,10 +1103,10 @@ sub set_hold_shelf_expire_time {
     return undef unless $shelf_expire;
 
     $start_time = ($start_time) ?
-        DateTime::Format::ISO8601->new->parse_datetime(cleanse_ISO8601($start_time)) :
+        DateTime::Format::ISO8601->new->parse_datetime(clean_ISO8601($start_time)) :
         DateTime->now(time_zone => 'local'); # without time_zone we get UTC ... yuck!
 
-    my $seconds = OpenSRF::Utils->interval_to_seconds($shelf_expire);
+    my $seconds = OpenILS::Utils::DateTime->interval_to_seconds($shelf_expire);
     my $expire_time = $start_time->add(seconds => $seconds);
 
     # if the shelf expire time overlaps with a pickup lib's
@@ -1117,7 +1117,7 @@ sub set_hold_shelf_expire_time {
 
     if($dateinfo) {
         my $dt_parser = DateTime::Format::ISO8601->new;
-        $expire_time = $dt_parser->parse_datetime(cleanse_ISO8601($dateinfo->{end}));
+        $expire_time = $dt_parser->parse_datetime(clean_ISO8601($dateinfo->{end}));
 
         # TODO: enable/disable time bump via setting?
         $expire_time->set(hour => '23', minute => '59', second => '59');
@@ -1305,8 +1305,8 @@ sub _hold_status {
                             dest_recv_time => {'!=' => undef},
                          })->[0];
         my $start_time = ($transit) ? $transit->dest_recv_time : $hold->capture_time;
-        $start_time    = DateTime::Format::ISO8601->new->parse_datetime(cleanse_ISO8601($start_time));
-        my $end_time   = $start_time->add(seconds => OpenSRF::Utils::interval_to_seconds($hs_wait_interval));
+        $start_time    = DateTime::Format::ISO8601->new->parse_datetime(clean_ISO8601($start_time));
+        my $end_time   = $start_time->add(seconds => OpenILS::Utils::DateTime->interval_to_seconds($hs_wait_interval));
 
         return 5 if $end_time > DateTime->now;
         return 4;
@@ -1456,7 +1456,7 @@ sub retrieve_hold_queue_status_impl {
         $user_org, OILS_SETTING_HOLD_ESIMATE_WAIT_INTERVAL, $e);
     my $min_wait = $U->ou_ancestor_setting_value(
         $user_org, 'circ.holds.min_estimated_wait_interval', $e);
-    $min_wait = OpenSRF::Utils::interval_to_seconds($min_wait || '0 seconds');
+    $min_wait = OpenILS::Utils::DateTime->interval_to_seconds($min_wait || '0 seconds');
     $default_wait ||= '0 seconds';
 
     # Estimated wait time is the average wait time across the set
@@ -1469,7 +1469,7 @@ sub retrieve_hold_queue_status_impl {
     for my $wait_data (@$hold_data) {
         my $count += $wait_data->{count};
         $combined_secs += $count *
-            OpenSRF::Utils::interval_to_seconds($wait_data->{avg_wait_time} || $default_wait);
+            OpenILS::Utils::DateTime->interval_to_seconds($wait_data->{avg_wait_time} || $default_wait);
         $num_potentials += $count;
     }
 
@@ -4324,7 +4324,7 @@ sub calculate_expire_time
     my $ou = shift;
     my $interval = $U->ou_ancestor_setting_value($ou, OILS_SETTING_HOLD_EXPIRE);
     if($interval) {
-        my $date = DateTime->now->add(seconds => OpenSRF::Utils::interval_to_seconds($interval));
+        my $date = DateTime->now->add(seconds => OpenILS::Utils::DateTime->interval_to_seconds($interval));
         return $U->epoch2ISO8601($date->epoch);
     }
     return undef;
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Money.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Money.pm
index 4fa1d1f..6b84a78 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Money.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Money.pm
@@ -32,7 +32,7 @@ use OpenILS::Utils::Penalty;
 use Business::Stripe;
 $Data::Dumper::Indent = 0;
 use OpenILS::Const qw/:const/;
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
 use DateTime::Format::ISO8601;
 my $parser = DateTime::Format::ISO8601->new;
 
@@ -1290,7 +1290,7 @@ __PACKAGE__->register_method(
 sub _to_epoch {
     my $ts = shift @_;
 
-    return $parser->parse_datetime(cleanse_ISO8601($ts))->epoch;
+    return $parser->parse_datetime(clean_ISO8601($ts))->epoch;
 }
 
 my %_statement_sort = (
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/NonCat.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/NonCat.pm
index 26b85d2..0d576cf 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/NonCat.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/NonCat.pm
@@ -5,7 +5,7 @@ use OpenSRF::EX qw(:try);
 use Data::Dumper;
 use DateTime;
 use DateTime::Format::ISO8601;
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
 use OpenSRF::Utils::Logger qw(:logger);
 use OpenILS::Application::AppUtils;
 use OpenILS::Utils::Fieldmapper;
@@ -186,7 +186,7 @@ sub noncat_due_date {
     my $otype = $e->retrieve_config_non_cataloged_type($circ->item_type) 
         or return $e->die_event;
 
-    my $duedate = $_dt_parser->parse_datetime( cleanse_ISO8601($circ->circ_time) );
+    my $duedate = $_dt_parser->parse_datetime( clean_ISO8601($circ->circ_time) );
     $duedate = $duedate
         ->add( seconds => interval_to_seconds($otype->circ_duration) )
         ->strftime('%FT%T%z');
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Collections.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Collections.pm
index a377029..b451cbd 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Collections.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Collections.pm
@@ -3,7 +3,7 @@ use strict; use warnings;
 use OpenSRF::EX qw(:try);
 use OpenILS::Application::AppUtils;
 use OpenSRF::Utils::Logger qw(:logger);
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
 use OpenILS::Application;
 use OpenILS::Utils::Fieldmapper;
 use base 'OpenILS::Application';
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Serial.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Serial.pm
index dfe9878..fe509e9 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Serial.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Serial.pm
@@ -43,7 +43,7 @@ use base qw/OpenILS::Application/;
 use OpenILS::Application::AppUtils;
 use OpenILS::Event;
 use OpenSRF::AppSession;
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
 use OpenSRF::Utils::Logger qw/:logger/;
 use OpenILS::Utils::CStoreEditor q/:funcs/;
 use OpenILS::Utils::Fieldmapper;
@@ -1060,7 +1060,7 @@ sub make_prediction_values {
         $logger->debug('make_prediction_values reviving holdings: ' . OpenSRF::Utils::JSON->perl2JSON($predict_from_siss));
         $options->{predict_from} = _revive_holding($predict_from_siss->holding_code, $caption_field, 1); # fresh MFHD Record, so we simply default to 1 for seqno
         if ($fake_chron_needed) {
-            $options->{faked_chron_date} = DateTime::Format::ISO8601->new->parse_datetime(cleanse_ISO8601($predict_from_siss->date_published));
+            $options->{faked_chron_date} = DateTime::Format::ISO8601->new->parse_datetime(clean_ISO8601($predict_from_siss->date_published));
         }
         $logger->debug('make_prediction_values predicting with options: ' . OpenSRF::Utils::JSON->perl2JSON($options));
         push( @predictions, _generate_issuance_values($mfhd, $options) );
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Driver/Pg/QueryParser.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Driver/Pg/QueryParser.pm
index 0d3c411..9410851 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Driver/Pg/QueryParser.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Driver/Pg/QueryParser.pm
@@ -4,7 +4,7 @@ use warnings;
 package OpenILS::Application::Storage::Driver::Pg::QueryParser;
 use OpenILS::Application::Storage::QueryParser;
 use base 'QueryParser';
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
 use OpenSRF::Utils::JSON;
 use OpenILS::Application::AppUtils;
 use OpenILS::Utils::CStoreEditor;
@@ -755,7 +755,7 @@ __PACKAGE__->add_search_modifier( 'metabib' );
 package OpenILS::Application::Storage::Driver::Pg::QueryParser::query_plan;
 use base 'QueryParser::query_plan';
 use OpenSRF::Utils::Logger qw($logger);
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
 use Data::Dumper;
 use OpenILS::Application::AppUtils;
 use OpenILS::Utils::Normalize qw/search_normalize/;
@@ -1671,7 +1671,7 @@ sub flatten {
                             # useless use of filter
                         } else {
                             # "before $cend"
-                            $cend = cleanse_ISO8601($cend);
+                            $cend = clean_ISO8601($cend);
                             $where .= $joiner if $where ne '';
                             $where .= "bre.$datefilter <= \$_$$\$$cend\$_$$\$";
                         }
@@ -1680,14 +1680,14 @@ sub flatten {
                         if ($cstart eq '-infinity') {
                             # useless use of filter
                         } else { # "after $cstart"
-                            $cstart = cleanse_ISO8601($cstart);
+                            $cstart = clean_ISO8601($cstart);
                             $where .= $joiner if $where ne '';
                             $where .= "bre.$datefilter >= \$_$$\$$cstart\$_$$\$";
                         }
                     } else { # both supplied
                         # "between $cstart and $cend"
-                        $cstart = cleanse_ISO8601($cstart);
-                        $cend = cleanse_ISO8601($cend);
+                        $cstart = clean_ISO8601($cstart);
+                        $cend = clean_ISO8601($cend);
                         $where .= $joiner if $where ne '';
                         $where .= "bre.$datefilter BETWEEN \$_$$\$$cstart\$_$$\$ AND \$_$$\$$cend\$_$$\$";
                     }
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Publisher.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Publisher.pm
index db78f30..dd90f17 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Publisher.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Publisher.pm
@@ -5,6 +5,7 @@ our $VERSION = 1;
 use Digest::MD5 qw/md5_hex/;
 use OpenSRF::EX qw/:try/;
 use OpenSRF::Utils;
+use OpenILS::Utils::DateTime;
 use OpenSRF::Utils::Logger qw/:level/;
 use OpenILS::Utils::Fieldmapper;
 
@@ -112,7 +113,7 @@ sub cachable_wrapper {
         OpenSRF::Utils::Cache->new->put_cache(
             $cache_key =>
             [@res[int($cache_page * $cache_args{cache_page_size}) .. int(($cache_page + 1) * $cache_args{cache_page_size}) ]] =>
-            OpenSRF::Utils->interval_to_seconds( $cache_args{timeout} )
+            OpenILS::Utils::DateTime->interval_to_seconds( $cache_args{timeout} )
         );
     } catch Error with {
         my $e = shift;
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Publisher/action.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Publisher/action.pm
index 3c69f33..045c5e5 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Publisher/action.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Publisher/action.pm
@@ -3,7 +3,7 @@ use parent qw/OpenILS::Application::Storage::Publisher/;
 use strict;
 use warnings;
 use OpenSRF::Utils::Logger qw/:level :logger/;
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
 use OpenSRF::Utils::JSON;
 use OpenSRF::AppSession;
 use OpenSRF::EX qw/:try/;
@@ -1218,7 +1218,7 @@ sub new_hold_copy_targeter {
             $_->delete for (@oldmaps);
 
             if ($hold->expire_time) {
-                my $ex_time = $parser->parse_datetime( cleanse_ISO8601( $hold->expire_time ) );
+                my $ex_time = $parser->parse_datetime( clean_ISO8601( $hold->expire_time ) );
                 if ( DateTime->compare($ex_time, DateTime->now) < 0 ) {
 
                     # cancel cause = un-targeted expiration
@@ -1677,7 +1677,7 @@ sub process_recall {
 
         # Give the user a new due date of either a full recall threshold,
         # or the return interval, whichever is further in the future
-        my $threshold_date = DateTime::Format::ISO8601->parse_datetime(cleanse_ISO8601($circ->xact_start))->add(seconds => interval_to_seconds($recall_threshold))->iso8601();
+        my $threshold_date = DateTime::Format::ISO8601->parse_datetime(clean_ISO8601($circ->xact_start))->add(seconds => interval_to_seconds($recall_threshold))->iso8601();
         if (DateTime->compare(DateTime::Format::ISO8601->parse_datetime($threshold_date), DateTime::Format::ISO8601->parse_datetime($return_date)) == 1) {
             $return_date = $threshold_date;
         }
@@ -1756,7 +1756,7 @@ sub reservation_targeter {
 
             die "OK\n" if (!$bresv or $bresv->capture_time or $bresv->cancel_time);
 
-            my $end_time = $parser->parse_datetime( cleanse_ISO8601( $bresv->end_time ) );
+            my $end_time = $parser->parse_datetime( clean_ISO8601( $bresv->end_time ) );
             if (DateTime->compare($end_time, DateTime->now) < 0) {
 
                 # cancel cause = un-targeted expiration
@@ -1831,8 +1831,8 @@ sub reservation_targeter {
 
                     if (@$circs) {
                         my $due_date = $circs->[0]->due_date;
-                        $due_date = $parser->parse_datetime( cleanse_ISO8601( $due_date ) );
-                        my $start_time = $parser->parse_datetime( cleanse_ISO8601( $bresv->start_time ) );
+                        $due_date = $parser->parse_datetime( clean_ISO8601( $due_date ) );
+                        my $start_time = $parser->parse_datetime( clean_ISO8601( $bresv->start_time ) );
                         if (DateTime->compare($start_time, $due_date) < 0) {
                             $conflicts{$res->id} = $circs->[0]->to_fieldmapper;
                             next;
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Publisher/actor.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Publisher/actor.pm
index 686d960..0c1f0a5 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Publisher/actor.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Publisher/actor.pm
@@ -2,7 +2,7 @@ package OpenILS::Application::Storage::Publisher::actor;
 use base qw/OpenILS::Application::Storage/;
 use OpenILS::Application::Storage::CDBI::actor;
 use OpenSRF::Utils::Logger qw/:level/;
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
 use OpenILS::Utils::Fieldmapper;
 use OpenSRF::Utils::SettingsClient;
 use OpenILS::Application::AppUtils;
@@ -263,8 +263,8 @@ sub make_closure_spanset {
 
         $spanset = $spanset->union(
             DateTime::Span->new(
-                start => $_dt_parser->parse_datetime(cleanse_ISO8601($c->{close_start})),
-                end   => $_dt_parser->parse_datetime(cleanse_ISO8601($c->{close_end}))
+                start => $_dt_parser->parse_datetime(clean_ISO8601($c->{close_start})),
+                end   => $_dt_parser->parse_datetime(clean_ISO8601($c->{close_end}))
             )
         );
     }
@@ -293,7 +293,7 @@ sub new_org_closed_overlap {
           LIMIT 1
     SQL
 
-    $date = cleanse_ISO8601($date);
+    $date = clean_ISO8601($date);
 
     my $target_date = $_dt_parser->parse_datetime( $date );
     my ($begin, $end) = ($target_date, $target_date);
@@ -312,7 +312,7 @@ sub new_org_closed_overlap {
             $begin->subtract( minutes => 1 );
 
             while ( my $_b = new_org_closed_overlap($self, $client, $ou, $begin->strftime('%FT%T%z'), -1, 1 ) ) {
-                $begin = $_dt_parser->parse_datetime( cleanse_ISO8601($_b->{start}) );
+                $begin = $_dt_parser->parse_datetime( clean_ISO8601($_b->{start}) );
             }
         }
 
@@ -320,7 +320,7 @@ sub new_org_closed_overlap {
             $end->add( minutes => 1 );
 
             while ( my $_a = new_org_closed_overlap($self, $client, $ou, $end->strftime('%FT%T%z'), 1, 1 ) ) {
-                $end = $_dt_parser->parse_datetime( cleanse_ISO8601($_a->{end}) );
+                $end = $_dt_parser->parse_datetime( clean_ISO8601($_a->{end}) );
             }
         }
     }
@@ -337,7 +337,7 @@ sub new_org_closed_overlap {
             $begin->subtract( minutes => 1 );
 
             while ( my $_b = new_org_closed_overlap($self, $client, $ou, $begin->strftime('%FT%T%z'), -1 ) ) {
-                $begin = $_dt_parser->parse_datetime( cleanse_ISO8601($_b->{start}) );
+                $begin = $_dt_parser->parse_datetime( clean_ISO8601($_b->{start}) );
             }
         }
     
@@ -348,7 +348,7 @@ sub new_org_closed_overlap {
 
 
             while ( my $_b = new_org_closed_overlap($self, $client, $ou, $end->strftime('%FT%T%z'), -1 ) ) {
-                $end = $_dt_parser->parse_datetime( cleanse_ISO8601($_b->{end}) );
+                $end = $_dt_parser->parse_datetime( clean_ISO8601($_b->{end}) );
             }
         }
     }
@@ -385,23 +385,23 @@ sub org_closed_overlap {
           LIMIT 1
     SQL
 
-    $date = cleanse_ISO8601($date);
+    $date = clean_ISO8601($date);
     my ($begin, $end) = ($date,$date);
 
     my $hoo = actor::org_unit::hours_of_operation->retrieve($ou);
 
     if (my $closure = actor::org_unit::closed_date->db_Main->selectrow_hashref( $sql, {}, $date, $ou )) {
-        $begin = cleanse_ISO8601($closure->{close_start});
-        $end = cleanse_ISO8601($closure->{close_end});
+        $begin = clean_ISO8601($closure->{close_start});
+        $end = clean_ISO8601($closure->{close_end});
 
         if ( $direction <= 0 ) {
             $before = $_dt_parser->parse_datetime( $begin );
             $before->subtract( minutes => 1 );
 
             while ( my $_b = org_closed_overlap($self, $client, $ou, $before->strftime('%FT%T%z'), -1, 1 ) ) {
-                $before = $_dt_parser->parse_datetime( cleanse_ISO8601($_b->{start}) );
+                $before = $_dt_parser->parse_datetime( clean_ISO8601($_b->{start}) );
             }
-            $begin = cleanse_ISO8601($before->strftime('%FT%T%z'));
+            $begin = clean_ISO8601($before->strftime('%FT%T%z'));
         }
 
         if ( $direction >= 0 ) {
@@ -409,9 +409,9 @@ sub org_closed_overlap {
             $after->add( minutes => 1 );
 
             while ( my $_a = org_closed_overlap($self, $client, $ou, $after->strftime('%FT%T%z'), 1, 1 ) ) {
-                $after = $_dt_parser->parse_datetime( cleanse_ISO8601($_a->{end}) );
+                $after = $_dt_parser->parse_datetime( clean_ISO8601($_a->{end}) );
             }
-            $end = cleanse_ISO8601($after->strftime('%FT%T%z'));
+            $end = clean_ISO8601($after->strftime('%FT%T%z'));
         }
     }
 
@@ -425,7 +425,7 @@ sub org_closed_overlap {
 
                 my $count = 1;
                 while ($hoo->$begin_open_meth eq '00:00:00' and $hoo->$begin_close_meth eq '00:00:00') {
-                    $begin = cleanse_ISO8601($_dt_parser->parse_datetime( $begin )->subtract( days => 1)->strftime('%FT%T%z'));
+                    $begin = clean_ISO8601($_dt_parser->parse_datetime( $begin )->subtract( days => 1)->strftime('%FT%T%z'));
                     $begin_dow++;
                     $begin_dow %= 7;
                     $count++;
@@ -438,7 +438,7 @@ sub org_closed_overlap {
                     $before = $_dt_parser->parse_datetime( $begin );
                     $before->subtract( minutes => 1 );
                     while ( my $_b = org_closed_overlap($self, $client, $ou, $before->strftime('%FT%T%z'), -1 ) ) {
-                        $before = $_dt_parser->parse_datetime( cleanse_ISO8601($_b->{start}) );
+                        $before = $_dt_parser->parse_datetime( clean_ISO8601($_b->{start}) );
                     }
                 }
             }
@@ -450,7 +450,7 @@ sub org_closed_overlap {
     
                 $count = 1;
                 while ($hoo->$end_open_meth eq '00:00:00' and $hoo->$end_close_meth eq '00:00:00') {
-                    $end = cleanse_ISO8601($_dt_parser->parse_datetime( $end )->add( days => 1)->strftime('%FT%T%z'));
+                    $end = clean_ISO8601($_dt_parser->parse_datetime( $end )->add( days => 1)->strftime('%FT%T%z'));
                     $end_dow++;
                     $end_dow %= 7;
                     $count++;
@@ -464,9 +464,9 @@ sub org_closed_overlap {
                     $after->add( minutes => 1 );
 
                     while ( my $_a = org_closed_overlap($self, $client, $ou, $after->strftime('%FT%T%z'), 1 ) ) {
-                        $after = $_dt_parser->parse_datetime( cleanse_ISO8601($_a->{end}) );
+                        $after = $_dt_parser->parse_datetime( clean_ISO8601($_a->{end}) );
                     }
-                    $end = cleanse_ISO8601($after->strftime('%FT%T%z'));
+                    $end = clean_ISO8601($after->strftime('%FT%T%z'));
                 }
             }
 
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger.pm
index 3336dcb..9027beb 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger.pm
@@ -10,7 +10,7 @@ use OpenSRF::AppSession;
 use OpenSRF::MultiSession;
 use OpenSRF::Utils::SettingsClient;
 use OpenSRF::Utils::Logger qw/$logger/;
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
 
 use DateTime;
 use DateTime::Format::ISO8601;
@@ -93,7 +93,7 @@ sub create_active_events_for_object {
 
             if (my $dfield = $def->delay_field) {
                 if ($target->$dfield()) {
-                    $date = DateTime::Format::ISO8601->new->parse_datetime( cleanse_ISO8601($target->$dfield) );
+                    $date = DateTime::Format::ISO8601->new->parse_datetime( clean_ISO8601($target->$dfield) );
                 } else {
                     next;
                 }
@@ -187,7 +187,7 @@ sub create_event_for_object_and_def {
 
             if (my $dfield = $def->delay_field) {
                 if ($target->$dfield()) {
-                    $date = DateTime::Format::ISO8601->new->parse_datetime( cleanse_ISO8601($target->$dfield) );
+                    $date = DateTime::Format::ISO8601->new->parse_datetime( clean_ISO8601($target->$dfield) );
                 } else {
                     next;
                 }
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Reactor.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Reactor.pm
index f334f66..bf6b67e 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Reactor.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Reactor.pm
@@ -6,7 +6,7 @@ use DateTime;
 use DateTime::Format::ISO8601;
 use Unicode::Normalize;
 use XML::LibXML;
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
 use OpenSRF::Utils::Logger qw(:logger);
 use OpenSRF::Utils::JSON;
 use OpenILS::Application::AppUtils;
@@ -43,7 +43,7 @@ $_TT_helpers = {
     # turns a date into something TT can understand
     format_date => sub {
         my $date = shift;
-        $date = DateTime::Format::ISO8601->new->parse_datetime(cleanse_ISO8601($date));
+        $date = DateTime::Format::ISO8601->new->parse_datetime(clean_ISO8601($date));
         return sprintf(
             "%0.2d:%0.2d:%0.2d %0.2d-%0.2d-%0.4d",
             $date->hour,
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Validator.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Validator.pm
index c45d1ea..ad4e4f4 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Validator.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Validator.pm
@@ -2,7 +2,7 @@ package OpenILS::Application::Trigger::Validator;
 use strict; use warnings;
 use DateTime;
 use DateTime::Format::ISO8601;
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
 use OpenSRF::Utils::Logger qw/:logger/;
 use OpenILS::Const qw/:const/;
 use OpenILS::Application::AppUtils;
@@ -47,7 +47,7 @@ sub MinPassiveTargetAge {
         return 0; # no-op false
     }
 
-    my $delay_field_ts = DateTime::Format::ISO8601->new->parse_datetime(cleanse_ISO8601($target->$delay_field()));
+    my $delay_field_ts = DateTime::Format::ISO8601->new->parse_datetime(clean_ISO8601($target->$delay_field()));
 
     # to get the minimum time that the target must have aged to, add the min age to the delay field
     $delay_field_ts->add( seconds => interval_to_seconds( $env->{params}->{min_target_age} ) );
@@ -69,7 +69,7 @@ sub CircIsOverdue {
         return 0 if (!$self->MinPassiveTargetAge($env));
     }
 
-    my $due_date = DateTime::Format::ISO8601->new->parse_datetime(cleanse_ISO8601($circ->due_date));
+    my $due_date = DateTime::Format::ISO8601->new->parse_datetime(clean_ISO8601($circ->due_date));
     return 0 if $due_date > DateTime->now;
 
     return 1;
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/SIP.pm b/Open-ILS/src/perlmods/lib/OpenILS/SIP.pm
index e2639cc..500efa2 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/SIP.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/SIP.pm
@@ -23,7 +23,7 @@ use OpenSRF::AppSession;
 use OpenILS::Utils::Fieldmapper;
 use OpenSRF::Utils::SettingsClient;
 use OpenILS::Application::AppUtils;
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
 use DateTime::Format::ISO8601;
 
 my $U = 'OpenILS::Application::AppUtils';
@@ -147,7 +147,7 @@ sub format_date {
     return "" unless $date;
 
     my $dt = DateTime::Format::ISO8601->new->
-        parse_datetime(OpenSRF::Utils::cleanse_ISO8601($date));
+        parse_datetime(clean_ISO8601($date));
 
     # actor.usr.dob stores dates without time/timezone, which causes
     # DateTime to assume the date is stored as UTC.  Tell DateTime
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/SIP/Item.pm b/Open-ILS/src/perlmods/lib/OpenILS/SIP/Item.pm
index 0c59825..e727732 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/SIP/Item.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/SIP/Item.pm
@@ -9,7 +9,7 @@ use OpenILS::SIP::Transaction;
 use OpenILS::Application::AppUtils;
 # use Data::Dumper;
 use OpenILS::Const qw/:const/;
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
 use DateTime::Format::ISO8601;
 use OpenSRF::Utils::SettingsClient;
 my $U = 'OpenILS::Application::AppUtils';
@@ -404,7 +404,7 @@ sub hold_pickup_date {
         $shelf_expire_setting_cache{$hold->pickup_lib->id} = $interval;
 
         if($interval) {
-            my $seconds = OpenSRF::Utils->interval_to_seconds($interval);
+            my $seconds = OpenILS::Utils::DateTime->interval_to_seconds($interval);
             $date = DateTime->now->add(seconds => $seconds);
             $date = $date->strftime('%FT%T%z') if $date;
         }
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/SIP/Patron.pm b/Open-ILS/src/perlmods/lib/OpenILS/SIP/Patron.pm
index 9e593e5..3b458cb 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/SIP/Patron.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/SIP/Patron.pm
@@ -18,7 +18,7 @@ use OpenILS::SIP;
 use OpenILS::Application::AppUtils;
 use OpenILS::Application::Actor;
 use OpenILS::Const qw/:const/;
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
 use DateTime::Format::ISO8601;
 my $U = 'OpenILS::Application::AppUtils';
 
@@ -337,7 +337,7 @@ sub charge_ok {
     my $circ_is_blocked = 0;
 
     # compute expiration date for borrowing privileges
-    my $expire = DateTime::Format::ISO8601->new->parse_datetime(cleanse_ISO8601($u->expire_date));
+    my $expire = DateTime::Format::ISO8601->new->parse_datetime(clean_ISO8601($u->expire_date));
 
     $circ_is_blocked =
         (($u->barred eq 't') or
@@ -356,7 +356,7 @@ sub renew_ok {
     my $renew_is_blocked = 0;
 
     # compute expiration date for borrowing privileges
-    my $expire = DateTime::Format::ISO8601->new->parse_datetime(cleanse_ISO8601($u->expire_date));
+    my $expire = DateTime::Format::ISO8601->new->parse_datetime(clean_ISO8601($u->expire_date));
 
     $renew_is_blocked =
         (($u->barred eq 't') or
@@ -382,7 +382,7 @@ sub hold_ok {
     my $hold_is_blocked = 0;
 
     # compute expiration date for borrowing privileges
-    my $expire = DateTime::Format::ISO8601->new->parse_datetime(cleanse_ISO8601($u->expire_date));
+    my $expire = DateTime::Format::ISO8601->new->parse_datetime(clean_ISO8601($u->expire_date));
 
     $hold_is_blocked =
         (($u->barred eq 't') or
@@ -450,7 +450,7 @@ sub screen_msg {
     return $b if $u->standing_penalties and @{$u->standing_penalties};
 
     # has the patron account expired?
-    my $expire = DateTime::Format::ISO8601->new->parse_datetime(cleanse_ISO8601($u->expire_date));
+    my $expire = DateTime::Format::ISO8601->new->parse_datetime(clean_ISO8601($u->expire_date));
     return $b if CORE::time > $expire->epoch;
 
     return '';
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Utils/DateTime.pm b/Open-ILS/src/perlmods/lib/OpenILS/Utils/DateTime.pm
new file mode 100644
index 0000000..d622480
--- /dev/null
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Utils/DateTime.pm
@@ -0,0 +1,246 @@
+package OpenILS::Utils::DateTime;
+
+use Time::Local;
+use Errno;
+use POSIX;
+use FileHandle;
+use Digest::MD5 qw(md5 md5_hex md5_base64);
+use Exporter;
+use DateTime;
+use DateTime::Format::ISO8601;
+use DateTime::TimeZone;
+
+=head1 NAME
+
+OpenILS::Utils::DateTime;
+
+=head1 DESCRIPTION
+
+This contains several routines for doing date and time calculation. This
+is derived from the date/time routines from OpenSRF::Utils.
+
+=head1 VERSION
+
+=cut
+
+our $VERSION = 1.000;
+
+use vars qw/@ISA $AUTOLOAD %EXPORT_TAGS @EXPORT_OK @EXPORT/;
+push @ISA, 'Exporter';
+
+%EXPORT_TAGS = (
+	datetime	=> [qw(clean_ISO8601 gmtime_ISO8601 interval_to_seconds seconds_to_interval)],
+);
+Exporter::export_ok_tags('datetime');  # add aa, cc and dd to @EXPORT_OK
+
+our $date_parser = DateTime::Format::ISO8601->new;
+
+=head1 METHODS
+
+
+=cut
+
+sub AUTOLOAD {
+	my $self = shift;
+	my $type = ref($self) or return undef;
+
+	my $name = $AUTOLOAD;
+	$name =~ s/.*://;   # strip fully-qualified portion
+
+	if (defined($_[0])) {
+		return $self->{$name} = shift;
+	}
+	return $self->{$name};
+}
+
+=head2 $thing->interval_to_seconds('interval') OR interval_to_seconds('interval')
+
+=head2 $thing->seconds_to_interval($seconds) OR seconds_to_interval($seconds)
+
+Returns the number of seconds for any interval passed, or the interval for the seconds.
+This is the generic version of B<interval> listed below.
+
+The interval must match the regex I</\s*\+?\s*(\d+)\s*(\w{1})\w*\s*/g>, for example
+B<2 weeks, 3 d and 1hour + 17 Months> or
+B<1 year, 5 Months, 2 weeks, 3 days and 1 hour of seconds> meaning 46148400 seconds.
+
+	my $expire_time = time() + $thing->interval_to_seconds('17h 9m');
+
+The time size indicator may be one of
+
+=over 2
+
+=item s[econd[s]]
+
+for seconds
+
+=item m[inute[s]]
+
+for minutes
+
+=item h[our[s]]
+
+for hours
+
+=item d[ay[s]]
+
+for days
+
+=item w[eek[s]]
+
+for weeks
+
+=item M[onth[s]]
+
+for months (really (365 * 1d)/12 ... that may get smarter, though)
+
+=item y[ear[s]]
+
+for years (this is 365 * 1d)
+
+=back
+
+=cut
+sub interval_to_seconds {
+	my $self = shift;
+        my $interval = shift || $self;
+
+	$interval =~ s/(\d{2}):(\d{2}):(\d{2})/ $1 h $2 min $3 s /go;
+
+        $interval =~ s/and/,/g;
+        $interval =~ s/,/ /g;
+
+        my $amount = 0;
+        while ($interval =~ /\s*([\+-]?)\s*(\d+)\s*(\w+)\s*/g) {
+		my ($sign, $count, $type) = ($1, $2, $3);
+		$count = "$sign$count" if ($sign);
+                $amount += $count if ($type =~ /^s/);
+                $amount += 60 * $count if ($type =~ /^m(?!o)/oi);
+                $amount += 60 * 60 * $count if ($type =~ /^h/);
+                $amount += 60 * 60 * 24 * $count if ($type =~ /^d/oi);
+                $amount += 60 * 60 * 24 * 7 * $count if ($type =~ /^w/oi);
+                $amount += ((60 * 60 * 24 * 365)/12) * $count if ($type =~ /^mo/io);
+                $amount += 60 * 60 * 24 * 365 * $count if ($type =~ /^y/oi);
+        }
+        return $amount;
+}
+
+sub seconds_to_interval {
+	my $self = shift;
+        my $interval = shift || $self;
+
+        my $limit = shift || 's';
+        $limit =~ s/^(.)/$1/o;
+
+        my ($y,$ym,$M,$Mm,$w,$wm,$d,$dm,$h,$hm,$m,$mm,$s,$string);
+        my ($year, $month, $week, $day, $hour, $minute, $second) =
+                ('year','Month','week','day', 'hour', 'minute', 'second');
+
+        if ($y = int($interval / (60 * 60 * 24 * 365))) {
+                $string = "$y $year". ($y > 1 ? 's' : '');
+                $ym = $interval % (60 * 60 * 24 * 365);
+        } else {
+                $ym = $interval;
+        }
+        return $string if ($limit eq 'y');
+
+        if ($M = int($ym / ((60 * 60 * 24 * 365)/12))) {
+                $string .= ($string ? ', ':'')."$M $month". ($M > 1 ? 's' : '');
+                $Mm = $ym % ((60 * 60 * 24 * 365)/12);
+        } else {
+                $Mm = $ym;
+        }
+        return $string if ($limit eq 'M');
+
+        if ($w = int($Mm / 604800)) {
+                $string .= ($string ? ', ':'')."$w $week". ($w > 1 ? 's' : '');
+                $wm = $Mm % 604800;
+        } else {
+                $wm = $Mm;
+        }
+        return $string if ($limit eq 'w');
+
+        if ($d = int($wm / 86400)) {
+                $string .= ($string ? ', ':'')."$d $day". ($d > 1 ? 's' : '');
+                $dm = $wm % 86400;
+        } else {
+                $dm = $wm;
+        }
+        return $string if ($limit eq 'd');
+
+        if ($h = int($dm / 3600)) {
+                $string .= ($string ? ', ' : '')."$h $hour". ($h > 1 ? 's' : '');
+                $hm = $dm % 3600;
+        } else {
+                $hm = $dm;
+        }
+        return $string if ($limit eq 'h');
+
+        if ($m = int($hm / 60)) {
+                $string .= ($string ? ', ':'')."$m $minute". ($m > 1 ? 's' : '');
+                $mm = $hm % 60;
+        } else {
+                $mm = $hm;
+        }
+        return $string if ($limit eq 'm');
+
+        if ($s = int($mm)) {
+                $string .= ($string ? ', ':'')."$s $second". ($s > 1 ? 's' : '');
+        } else {
+                $string = "0s" unless ($string);
+        }
+        return $string;
+}
+
+sub gmtime_ISO8601 {
+	my $self = shift;
+	my @date = gmtime;
+
+	my $y = $date[5] + 1900;
+	my $M = $date[4] + 1;
+	my $d = $date[3];
+	my $h = $date[2];
+	my $m = $date[1];
+	my $s = $date[0];
+
+	return sprintf('%d-%0.2d-%0.2dT%0.2d:%0.2d:%0.2d+00:00', $y, $M, $d, $h, $m, $s);
+}
+
+sub clean_ISO8601 {
+	my $self = shift;
+	my $date = shift || $self;
+	if ($date =~ /^\s*(\d{4})-?(\d{2})-?(\d{2})/o) {
+		my $new_date = "$1-$2-$3";
+
+		if ($date =~/(\d{2}):(\d{2}):(\d{2})/o) {
+			$new_date .= "T$1:$2:$3";
+
+			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)
+			} else {
+				$z =  DateTime::TimeZone::offset_as_string(
+					DateTime::TimeZone
+						->new( name => 'local' )
+						->offset_for_datetime(
+							$date_parser->parse_datetime($new_date)
+						)
+				);
+			}
+
+			if (length($z) > 3 && index($z, ':') == -1) {
+				substr($z,3,0) = ':';
+				substr($z,6,0) = ':' if (length($z) > 6);
+			}
+		
+			$new_date .= $z;
+		} else {
+			$new_date .= "T00:00:00";
+		}
+
+		return $new_date;
+	}
+	return $date;
+}
+
+1;
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Utils/HoldTargeter.pm b/Open-ILS/src/perlmods/lib/OpenILS/Utils/HoldTargeter.pm
index 9aab446..392822a 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Utils/HoldTargeter.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Utils/HoldTargeter.pm
@@ -19,7 +19,7 @@ use DateTime;
 use OpenSRF::AppSession;
 use OpenSRF::Utils::Logger qw(:logger);
 use OpenSRF::Utils::JSON;
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
 use OpenILS::Application::AppUtils;
 use OpenILS::Utils::CStoreEditor qw/:funcs/;
 
@@ -161,7 +161,7 @@ sub init {
 
     if ($self->{soft_retarget_interval}) {
 
-        my $secs = OpenSRF::Utils->interval_to_seconds(
+        my $secs = OpenILS::Utils::DateTime->interval_to_seconds(
             $self->{soft_retarget_interval});
 
         $self->{soft_retarget_time} = 
@@ -176,7 +176,7 @@ sub init {
     # it overrides the retarget_interval.
     my $next_check_secs = 
         $self->{next_check_interval} ?
-        OpenSRF::Utils->interval_to_seconds($self->{next_check_interval}) :
+        OpenILS::Utils::DateTime->interval_to_seconds($self->{next_check_interval}) :
         $retarget_seconds;
 
     my $next_check_date = 
@@ -258,7 +258,7 @@ use strict;
 use warnings;
 use DateTime;
 use OpenSRF::AppSession;
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
 use OpenSRF::Utils::Logger qw(:logger);
 use OpenILS::Application::AppUtils;
 use OpenILS::Utils::CStoreEditor qw/:funcs/;
@@ -403,7 +403,7 @@ sub handle_expired_hold {
     return 1 unless $hold->expire_time;
 
     my $ex_time =
-        $dt_parser->parse_datetime(cleanse_ISO8601($hold->expire_time));
+        $dt_parser->parse_datetime(clean_ISO8601($hold->expire_time));
     return 1 unless 
         DateTime->compare($ex_time, DateTime->now(time_zone => 'local')) < 0;
 
@@ -781,7 +781,7 @@ sub inspect_previous_target {
         # soft_retarget_time and the retarget_time.
 
         my $pct = $dt_parser->parse_datetime(
-            cleanse_ISO8601($hold->prev_check_time));
+            clean_ISO8601($hold->prev_check_time));
 
         $soft_retarget =
             DateTime->compare($pct, $self->parent->{retarget_time}) > 0;
@@ -1184,7 +1184,7 @@ sub process_recalls {
     # Give the user a new due date of either a full recall threshold,
     # or the return interval, whichever is further in the future.
     my $threshold_date = DateTime::Format::ISO8601
-        ->parse_datetime(cleanse_ISO8601($circ->xact_start))
+        ->parse_datetime(clean_ISO8601($circ->xact_start))
         ->add(seconds => interval_to_seconds($threshold))
         ->iso8601();
 
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Utils/Penalty.pm b/Open-ILS/src/perlmods/lib/OpenILS/Utils/Penalty.pm
index 94c561c..c91bbc8 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/Utils/Penalty.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/Utils/Penalty.pm
@@ -4,7 +4,7 @@ use DateTime;
 use Data::Dumper;
 use OpenSRF::EX qw(:try);
 use OpenSRF::Utils::Cache;
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
 use OpenILS::Application::AppUtils;
 use OpenSRF::Utils::Logger qw(:logger);
 use OpenILS::Utils::CStoreEditor qw/:funcs/;
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm
index eeeba4a..2bf6704 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm
@@ -6,7 +6,7 @@ use Digest::MD5 qw(md5_hex);
 use Apache2::Const -compile => qw(OK DECLINED FORBIDDEN HTTP_INTERNAL_SERVER_ERROR REDIRECT HTTP_BAD_REQUEST);
 use OpenSRF::AppSession;
 use OpenSRF::EX qw/:try/;
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
 use OpenSRF::Utils::JSON;
 use OpenSRF::Utils::Logger qw/$logger/;
 use OpenILS::Application::AppUtils;
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Util.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Util.pm
index 3cb0799..730586a 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Util.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Util.pm
@@ -267,7 +267,7 @@ sub init_ro_object_cache {
             $date = '000' . $date;
         }
 
-        my $cleansed_date = cleanse_ISO8601($date);
+        my $cleansed_date = clean_ISO8601($date);
 
         $date = DateTime::Format::ISO8601->new->parse_datetime($cleansed_date);
         if ($context_org) {
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/Exporter.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/Exporter.pm
index 8508ab6..576dffd 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/Exporter.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/Exporter.pm
@@ -16,7 +16,7 @@ use Data::Dumper;
 use Text::CSV;
 
 use OpenSRF::EX qw(:try);
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
 use OpenSRF::Utils::Cache;
 use OpenSRF::System;
 use OpenSRF::AppSession;
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/SuperCat.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/SuperCat.pm
index a5fea7e..b43d266 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/SuperCat.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/SuperCat.pm
@@ -13,7 +13,7 @@ use SRU::Request;
 use SRU::Response;
 
 use OpenSRF::EX qw(:try);
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
 use OpenSRF::Utils::Cache;
 use OpenSRF::System;
 use OpenSRF::AppSession;
@@ -1639,7 +1639,7 @@ sub create_record_feed {
         }
 
         $node->id($item_tag);
-        #$node->update_ts(cleanse_ISO8601($record->edit_date));
+        #$node->update_ts(clean_ISO8601($record->edit_date));
         $node->link(alternate => $feed->unapi . "?id=$item_tag&format=opac" => 'text/html') if ($flesh > 0);
         $node->link(slimpac => $feed->unapi . "?id=$item_tag&format=htmlholdings-full" => 'text/html') if ($flesh > 0);
         $node->link(opac => $feed->unapi . "?id=$item_tag&format=opac") if ($flesh > 0);
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/SuperCat/Feed.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/SuperCat/Feed.pm
index 56146cb..9206409 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/SuperCat/Feed.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/SuperCat/Feed.pm
@@ -229,7 +229,7 @@ sub description {};
 
 package OpenILS::WWW::SuperCat::Feed::atom;
 use base 'OpenILS::WWW::SuperCat::Feed';
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
 
 sub new {
     my $class = shift;
diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/TemplateBatchBibUpdate.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/TemplateBatchBibUpdate.pm
index fa4fc5d..33d0f04 100644
--- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/TemplateBatchBibUpdate.pm
+++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/TemplateBatchBibUpdate.pm
@@ -16,7 +16,7 @@ use Data::Dumper;
 use Text::CSV;
 
 use OpenSRF::EX qw(:try);
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
 use OpenSRF::Utils::Cache;
 use OpenSRF::System;
 use OpenSRF::AppSession;
diff --git a/Open-ILS/src/perlmods/live_t/03-overdue_circ.t b/Open-ILS/src/perlmods/live_t/03-overdue_circ.t
index f803843..8323bcf 100644
--- a/Open-ILS/src/perlmods/live_t/03-overdue_circ.t
+++ b/Open-ILS/src/perlmods/live_t/03-overdue_circ.t
@@ -16,7 +16,7 @@ my $script = OpenILS::Utils::TestUtils->new();
 
 use DateTime;
 use DateTime::Format::ISO8601;
-use OpenSRF::Utils qw/cleanse_ISO8601/;
+use OpenILS::Utils::DateTime qw/clean_ISO8601/;
 
 our $apputils = 'OpenILS::Application::AppUtils';
 
@@ -144,8 +144,8 @@ if (my $bill_resp = $bill_req->recv) {
     }
 }
 
-my $xact_start = DateTime::Format::ISO8601->parse_datetime(cleanse_ISO8601($circ->xact_start));
-my $due_date = DateTime::Format::ISO8601->parse_datetime(cleanse_ISO8601($circ->due_date));
+my $xact_start = DateTime::Format::ISO8601->parse_datetime(clean_ISO8601($circ->xact_start));
+my $due_date = DateTime::Format::ISO8601->parse_datetime(clean_ISO8601($circ->due_date));
 
 # Rewrite history; technically we should rewrite status_changed_item on the copy as well, but, meh...
 $circ->xact_start( $xact_start->subtract( days => 20 )->iso8601() );
diff --git a/Open-ILS/src/perlmods/live_t/04-overdue_with_closed_dates.t b/Open-ILS/src/perlmods/live_t/04-overdue_with_closed_dates.t
index 780781c..ced78be 100644
--- a/Open-ILS/src/perlmods/live_t/04-overdue_with_closed_dates.t
+++ b/Open-ILS/src/perlmods/live_t/04-overdue_with_closed_dates.t
@@ -16,7 +16,7 @@ my $script = OpenILS::Utils::TestUtils->new();
 
 use DateTime;
 use DateTime::Format::ISO8601;
-use OpenSRF::Utils qw/cleanse_ISO8601/;
+use OpenILS::Utils::DateTime qw/clean_ISO8601/;
 
 our $apputils   = "OpenILS::Application::AppUtils";
 
@@ -196,8 +196,8 @@ if (my $bill_resp = $bill_req->recv) {
     }
 }
 
-my $xact_start = DateTime::Format::ISO8601->parse_datetime(cleanse_ISO8601($circ->xact_start));
-my $due_date = DateTime::Format::ISO8601->parse_datetime(cleanse_ISO8601($circ->due_date));
+my $xact_start = DateTime::Format::ISO8601->parse_datetime(clean_ISO8601($circ->xact_start));
+my $due_date = DateTime::Format::ISO8601->parse_datetime(clean_ISO8601($circ->due_date));
 
 # Rewrite history; technically we should rewrite status_changed_item on the copy as well, but, meh...
 $circ->xact_start( $xact_start->subtract( days => 20 )->iso8601() );
diff --git a/Open-ILS/src/perlmods/live_t/05-pay_bills.t b/Open-ILS/src/perlmods/live_t/05-pay_bills.t
index c93a586..032b7b2 100644
--- a/Open-ILS/src/perlmods/live_t/05-pay_bills.t
+++ b/Open-ILS/src/perlmods/live_t/05-pay_bills.t
@@ -16,7 +16,7 @@ my $script = OpenILS::Utils::TestUtils->new();
 
 use DateTime;
 use DateTime::Format::ISO8601;
-use OpenSRF::Utils qw/cleanse_ISO8601/;
+use OpenILS::Utils::DateTime qw/clean_ISO8601/;
 
 our $apputils   = "OpenILS::Application::AppUtils";
 
diff --git a/Open-ILS/src/perlmods/live_t/09-lp1198465_neg_balances.t b/Open-ILS/src/perlmods/live_t/09-lp1198465_neg_balances.t
index 4702a33..c72f7e2 100644
--- a/Open-ILS/src/perlmods/live_t/09-lp1198465_neg_balances.t
+++ b/Open-ILS/src/perlmods/live_t/09-lp1198465_neg_balances.t
@@ -11,7 +11,7 @@ use strict; use warnings;
 
 use DateTime;
 use DateTime::Format::ISO8601;
-use OpenSRF::Utils qw/cleanse_ISO8601/;
+use OpenILS::Utils::DateTime qw/clean_ISO8601/;
 use OpenILS::Utils::TestUtils;
 my $script = OpenILS::Utils::TestUtils->new();
 use Data::Dumper;
diff --git a/Open-ILS/src/perlmods/t/14-OpenILS-Utils.t b/Open-ILS/src/perlmods/t/14-OpenILS-Utils.t
index 548bea3..dc6e2a1 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 => 30;
+use Test::More tests => 39;
 use Test::Warn;
 use utf8;
 
@@ -21,6 +21,7 @@ use_ok( 'OpenILS::Utils::RemoteAccount' );
 use_ok( 'OpenILS::Utils::ZClient' );
 use_ok( 'OpenILS::Utils::EDIReader' );
 use_ok( 'OpenILS::Utils::HTTPClient' );
+use_ok( 'OpenILS::Utils::DateTime' );
 
 # LP 800269 - Test MFHD holdings for records that only contain a caption field
 my $co_marc = MARC::Record->new();
@@ -98,3 +99,11 @@ is($edi_msgs->[0]->{purchase_order}, '24', 'edi reader: PO number');
 is($edi_msgs->[1]->{invoice_ident}, '5TST084027', 'edi reader: invoice ident');
 is(scalar(@{$edi_msgs->[1]->{lineitems}}), '2', 'edi reader: lineitem count');
 
+is (OpenILS::Utils::DateTime::interval_to_seconds('1 second'), 1);
+is (OpenILS::Utils::DateTime::interval_to_seconds('1 minute'), 60);
+is (OpenILS::Utils::DateTime::interval_to_seconds('1 hour'), 3600);
+is (OpenILS::Utils::DateTime::interval_to_seconds('1 day'), 86400);
+is (OpenILS::Utils::DateTime::interval_to_seconds('1 week'), 604800);
+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);
diff --git a/Open-ILS/src/support-scripts/generate_circ_notices.pl b/Open-ILS/src/support-scripts/generate_circ_notices.pl
index 998cc22..b27f5d8 100755
--- a/Open-ILS/src/support-scripts/generate_circ_notices.pl
+++ b/Open-ILS/src/support-scripts/generate_circ_notices.pl
@@ -23,7 +23,7 @@ use Email::Send;
 use Getopt::Long;
 use Unicode::Normalize;
 use DateTime::Format::ISO8601;
-use OpenSRF::Utils qw/:datetime/;
+use OpenILS::Utils::DateTime qw/:datetime/;
 use OpenSRF::Utils::JSON;
 use OpenSRF::Utils::SettingsClient;
 use OpenSRF::AppSession;
@@ -128,12 +128,12 @@ sub main {
     $predue_notices = [$predue_notices] unless ref $predue_notices eq 'ARRAY'; 
 
     my @overdues = sort { 
-        OpenSRF::Utils->interval_to_seconds($a->{notify_interval}) <=> 
-        OpenSRF::Utils->interval_to_seconds($b->{notify_interval}) } @$overdue_notices;
+        OpenILS::Utils::DateTime->interval_to_seconds($a->{notify_interval}) <=> 
+        OpenILS::Utils::DateTime->interval_to_seconds($b->{notify_interval}) } @$overdue_notices;
 
     my @predues = sort { 
-        OpenSRF::Utils->interval_to_seconds($a->{notify_interval}) <=> 
-        OpenSRF::Utils->interval_to_seconds($b->{notify_interval}) } @$predue_notices;
+        OpenILS::Utils::DateTime->interval_to_seconds($a->{notify_interval}) <=> 
+        OpenILS::Utils::DateTime->interval_to_seconds($b->{notify_interval}) } @$predue_notices;
 
     for my $db (($opt_days_back) ? split(',', $opt_days_back) : 0) {
         if($opt_notice_types =~ /overdue/) {
@@ -174,7 +174,7 @@ sub global_overdue_output {
 sub generate_notice_set {
     my($notice, $type, $days_back) = @_;
 
-    my $notify_interval = OpenSRF::Utils->interval_to_seconds($notice->{notify_interval});
+    my $notify_interval = OpenILS::Utils::DateTime->interval_to_seconds($notice->{notify_interval});
     $notify_interval = -$notify_interval if $type eq 'overdue';
 
     my ($start_date, $end_date) = make_date_range($notify_interval - $days_back * 86400);
@@ -328,7 +328,7 @@ sub get_bib_attr {
 # provides a date that Template::Plugin::Date can parse
 sub parse_due_date {
     my $circ = shift;
-    my $due = DateTime::Format::ISO8601->new->parse_datetime(cleanse_ISO8601($circ->due_date));
+    my $due = DateTime::Format::ISO8601->new->parse_datetime(clean_ISO8601($circ->due_date));
     return sprintf(
         "%0.2d:%0.2d:%0.2d %0.2d-%0.2d-%0.4d",
         $due->hour,
diff --git a/Open-ILS/src/support-scripts/set_pbx_holidays.pl b/Open-ILS/src/support-scripts/set_pbx_holidays.pl
index 15483c0..aea2117 100755
--- a/Open-ILS/src/support-scripts/set_pbx_holidays.pl
+++ b/Open-ILS/src/support-scripts/set_pbx_holidays.pl
@@ -4,7 +4,7 @@ require "/openils/bin/oils_header.pl";
 
 use strict;
 use warnings;
-use OpenSRF::Utils qw/cleanse_ISO8601/;
+use OpenILS::Utils::DateTime qw/clean_ISO8601/;
 use OpenSRF::Utils::Logger qw/$logger/;
 use OpenSRF::Utils::SettingsClient;
 
@@ -16,7 +16,7 @@ use Getopt::Std;
 sub unixify {
     my ($stringy_ts) = @_;
     return (new DateTime::Format::ISO8601)->parse_datetime(
-        cleanse_ISO8601($stringy_ts)
+        clean_ISO8601($stringy_ts)
     )->epoch;
 }
 

-----------------------------------------------------------------------

Summary of changes:
 Open-ILS/src/offline/offline.pl                    |   11 +-
 Open-ILS/src/perlmods/MANIFEST                     |    1 +
 .../src/perlmods/lib/OpenILS/Application/Actor.pm  |    2 +-
 .../lib/OpenILS/Application/Actor/ClosedDates.pm   |    4 +-
 .../perlmods/lib/OpenILS/Application/Booking.pm    |    2 +-
 .../src/perlmods/lib/OpenILS/Application/Circ.pm   |   27 ++-
 .../lib/OpenILS/Application/Circ/CircCommon.pm     |   22 +-
 .../lib/OpenILS/Application/Circ/Circulate.pm      |   46 ++--
 .../perlmods/lib/OpenILS/Application/Circ/Holds.pm |   22 +-
 .../perlmods/lib/OpenILS/Application/Circ/Money.pm |    4 +-
 .../lib/OpenILS/Application/Circ/NonCat.pm         |    4 +-
 .../lib/OpenILS/Application/Collections.pm         |    2 +-
 .../src/perlmods/lib/OpenILS/Application/Serial.pm |    4 +-
 .../Application/Storage/Driver/Pg/QueryParser.pm   |   12 +-
 .../lib/OpenILS/Application/Storage/Publisher.pm   |    3 +-
 .../Application/Storage/Publisher/action.pm        |   12 +-
 .../OpenILS/Application/Storage/Publisher/actor.pm |   40 ++--
 .../perlmods/lib/OpenILS/Application/Trigger.pm    |    6 +-
 .../lib/OpenILS/Application/Trigger/Reactor.pm     |    4 +-
 .../lib/OpenILS/Application/Trigger/Validator.pm   |    6 +-
 Open-ILS/src/perlmods/lib/OpenILS/SIP.pm           |    4 +-
 Open-ILS/src/perlmods/lib/OpenILS/SIP/Item.pm      |    4 +-
 Open-ILS/src/perlmods/lib/OpenILS/SIP/Patron.pm    |   10 +-
 .../src/perlmods/lib/OpenILS/Utils/DateTime.pm     |  283 ++++++++++++++++++++
 .../src/perlmods/lib/OpenILS/Utils/HoldTargeter.pm |   14 +-
 Open-ILS/src/perlmods/lib/OpenILS/Utils/Penalty.pm |    2 +-
 .../src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm    |    2 +-
 .../perlmods/lib/OpenILS/WWW/EGCatLoader/Util.pm   |    2 +-
 Open-ILS/src/perlmods/lib/OpenILS/WWW/Exporter.pm  |    2 +-
 Open-ILS/src/perlmods/lib/OpenILS/WWW/SuperCat.pm  |    4 +-
 .../src/perlmods/lib/OpenILS/WWW/SuperCat/Feed.pm  |    2 +-
 .../lib/OpenILS/WWW/TemplateBatchBibUpdate.pm      |    2 +-
 Open-ILS/src/perlmods/live_t/03-overdue_circ.t     |    6 +-
 .../perlmods/live_t/04-overdue_with_closed_dates.t |    6 +-
 Open-ILS/src/perlmods/live_t/05-pay_bills.t        |    2 +-
 .../perlmods/live_t/09-lp1198465_neg_balances.t    |    2 +-
 Open-ILS/src/perlmods/t/14-OpenILS-Utils.t         |   50 ++++-
 .../src/support-scripts/generate_circ_notices.pl   |   14 +-
 Open-ILS/src/support-scripts/set_pbx_holidays.pl   |    4 +-
 .../src/templates/staff/circ/patron/t_checkout.tt2 |   10 +-
 .../js/ui/default/staff/circ/patron/items_out.js   |    8 +-
 41 files changed, 498 insertions(+), 169 deletions(-)
 create mode 100644 Open-ILS/src/perlmods/lib/OpenILS/Utils/DateTime.pm


hooks/post-receive
-- 
Evergreen ILS




More information about the open-ils-commits mailing list