Locale::parse_date_to_object: Unterstützung für volle Timestamps & explizite Formate
authorMoritz Bunkus <m.bunkus@linet-services.de>
Tue, 3 Jun 2014 12:31:04 +0000 (14:31 +0200)
committerMoritz Bunkus <m.bunkus@linet-services.de>
Tue, 3 Jun 2014 12:31:04 +0000 (14:31 +0200)
…und dafür Tests.

SL/Helper/DateTime.pm
SL/Locale.pm
SL/RP.pm
bin/mozilla/rp.pl
t/locale/parse_date_to_object.t [new file with mode: 0644]

index 3d6c78e..94c311f 100644 (file)
@@ -28,7 +28,7 @@ sub to_lxoffice {
 }
 
 sub from_kivitendo {
-  return $::locale->parse_date_to_object(\%::myconfig, $_[1]);
+  return $::locale->parse_date_to_object($_[1]);
 }
 
 sub from_lxoffice {
index a20620c..23a399e 100644 (file)
@@ -374,10 +374,23 @@ sub parse_date {
 }
 
 sub parse_date_to_object {
-  my $self           = shift;
-  my ($yy, $mm, $dd) = $self->parse_date(@_);
+  my ($self, $string, %params) = @_;
 
-  return $yy && $mm && $dd ? DateTime->new(year => $yy, month => $mm, day => $dd) : undef;
+  $params{dateformat}        ||= $::myconfig{dateformat}   || 'yy-mm-dd';
+  $params{numberformat}      ||= $::myconfig{numberformat} || '1,000.00';
+  my $num_separator            = $params{numberformat} =~ m{,\d+$} ? ',' : '.';
+
+  my ($date_str, $time_str)    = split m{\s+}, $string, 2;
+  my ($yy, $mm, $dd)           = $self->parse_date(\%params, $date_str);
+
+  my $millisecond              = 0;
+  my ($hour, $minute, $second) = split m/:/, $time_str;
+  ($second, $millisecond)      = split quotemeta($num_separator), $second, 2;
+  $millisecond                 = substr $millisecond, 0, 3;
+  $millisecond                .= '0' x (3 - length $millisecond);
+
+  return undef unless $yy && $mm && $dd;
+  return DateTime->new(year => $yy, month => $mm, day => $dd, hour => $hour * 1, minute => $minute * 1, second => $second * 1, nanosecond => $millisecond * 1000000);
 }
 
 sub format_date_object_to_time {
@@ -644,9 +657,14 @@ TODO: Describe new
 
 TODO: Describe parse_date
 
-=item C<parse_date_to_object>
+=item C<parse_date_to_object $string, %params>
+
+Parses a date and optional timestamp in C<$string> and returns an
+instance of L<DateTime>. The date and number formats used are the ones
+the user has currently selected. They can be overriden by passing them
+in as parameters to this function, though.
 
-TODO: Describe parse_date_to_object
+The time stamps can have up to millisecond precision.
 
 =item C<quote_special_chars>
 
index f6d9a88..969e8ad 100644 (file)
--- a/SL/RP.pm
+++ b/SL/RP.pm
@@ -58,7 +58,7 @@ sub get_balance_starting_date {
   my $asofdate = shift;
   return unless $asofdate;
 
-  $asofdate = $::locale->parse_date_to_object(\%::myconfig, $asofdate);
+  $asofdate = $::locale->parse_date_to_object($asofdate);
 
   my $form = $main::form;
   my $dbh  = $::form->get_standard_dbh;
@@ -85,7 +85,7 @@ sub get_balance_starting_date {
   # default.
   my ($closedto) = selectfirst_array_query($form, $dbh, 'SELECT closedto FROM defaults');
   if ($closedto) {
-    $closedto = $::locale->parse_date_to_object(\%::myconfig, $closedto);
+    $closedto = $::locale->parse_date_to_object($closedto);
     $closedto->subtract(years => 1) while ($asofdate - $closedto)->is_negative;
     $closedto->add(days => 1);
   };
@@ -93,11 +93,11 @@ sub get_balance_starting_date {
   my ($query, $startdate, $last_ob, $mindate);
   $query = qq|select max(transdate) from acc_trans where ob_transaction is true and transdate <= ?|;
   ($last_ob) = selectrow_query($::form, $dbh, $query, $::locale->format_date(\%::myconfig, $asofdate));
-  $last_ob = $::locale->parse_date_to_object(\%::myconfig, $last_ob) if $last_ob;
+  $last_ob = $::locale->parse_date_to_object($last_ob) if $last_ob;
 
   $query = qq|select min(transdate) from acc_trans|;
   ($mindate) = selectrow_query($::form, $dbh, $query);
-  $mindate = $::locale->parse_date_to_object(\%::myconfig, $mindate);
+  $mindate = $::locale->parse_date_to_object($mindate);
 
   # the default method is to use all transactions ($mindate)
 
index abffd97..860d38f 100644 (file)
@@ -1789,8 +1789,7 @@ sub generate_bwa {
     # if (defined ($form->{fromdate|todate}=='..'))
     # immer wahr
     if ($form->{fromdate}){
-      my ($yy, $mm, $dd) = $locale->parse_date(\%myconfig, $form->{fromdate});
-      my $datetime = $locale->parse_date_to_object(\%myconfig, $form->{fromdate});
+      my $datetime = $locale->parse_date_to_object($form->{fromdate});
       $datetime->set( month      => 1,
                       day        => 1);
       $form->{comparefromdate} = $locale->format_date(\%::myconfig, $datetime);
diff --git a/t/locale/parse_date_to_object.t b/t/locale/parse_date_to_object.t
new file mode 100644 (file)
index 0000000..4a042e4
--- /dev/null
@@ -0,0 +1,51 @@
+use strict;
+
+use Test::More;
+
+use lib 't';
+use Support::TestSetup;
+
+Support::TestSetup::login();
+
+sub is_dt {
+  my ($string, $expected, $msg, %args) = @_;
+
+  is($::locale->format_date_object($::locale->parse_date_to_object($string, %args), numberformat => '1000.00', dateformat => 'yy-mm-dd', precision => 'millisecond'), $expected, $msg);
+}
+
+is($::locale->parse_date_to_object('in-valid!'), undef, 'defaults, invalid');
+
+delete $::myconfig{numberformat};
+delete $::myconfig{dateformat};
+
+is_dt('2014-05-31',             '2014-05-31 00:00:00.000', 'defaults, no precision');
+is_dt('2014-05-31 2',           '2014-05-31 02:00:00.000', 'defaults, precision hour');
+is_dt('2014-05-31 2:04',        '2014-05-31 02:04:00.000', 'defaults, precision minute');
+is_dt('2014-05-31 2:04:59',     '2014-05-31 02:04:59.000', 'defaults, precision second');
+is_dt('2014-05-31 02:4:59.098', '2014-05-31 02:04:59.098', 'defaults, precision millisecond');
+is_dt('2014-05-31 02:4:59.09',  '2014-05-31 02:04:59.090', 'defaults, precision centisecond');
+
+$::myconfig{numberformat} = '1.000,00';
+$::myconfig{dateformat}   = 'dd.mm.yy';
+
+is_dt('31.05.2014',             '2014-05-31 00:00:00.000', 'myconfig numberformat 1.000,00 dateformat dd.mm.yy, no precision');
+is_dt('31.05.2014 2',           '2014-05-31 02:00:00.000', 'myconfig numberformat 1.000,00 dateformat dd.mm.yy, precision hour');
+is_dt('31.05.2014 2:04',        '2014-05-31 02:04:00.000', 'myconfig numberformat 1.000,00 dateformat dd.mm.yy, precision minute');
+is_dt('31.05.2014 2:04:59',     '2014-05-31 02:04:59.000', 'myconfig numberformat 1.000,00 dateformat dd.mm.yy, precision second');
+is_dt('31.05.2014 02:4:59,098', '2014-05-31 02:04:59.098', 'myconfig numberformat 1.000,00 dateformat dd.mm.yy, precision millisecond');
+
+is_dt('05/31/2014',             '2014-05-31 00:00:00.000', 'myconfig numberformat 1.000,00 explicit dateformat mm/dd/yy, no precision',          dateformat => 'mm/dd/yy');
+is_dt('05/31/2014 2',           '2014-05-31 02:00:00.000', 'myconfig numberformat 1.000,00 explicit dateformat mm/dd/yy, precision hour',        dateformat => 'mm/dd/yy');
+is_dt('05/31/2014 2:04',        '2014-05-31 02:04:00.000', 'myconfig numberformat 1.000,00 explicit dateformat mm/dd/yy, precision minute',      dateformat => 'mm/dd/yy');
+is_dt('05/31/2014 2:04:59',     '2014-05-31 02:04:59.000', 'myconfig numberformat 1.000,00 explicit dateformat mm/dd/yy, precision second',      dateformat => 'mm/dd/yy');
+is_dt('05/31/2014 02:4:59,098', '2014-05-31 02:04:59.098', 'myconfig numberformat 1.000,00 explicit dateformat mm/dd/yy, precision millisecond', dateformat => 'mm/dd/yy');
+
+is_dt('05/31/2014',             '2014-05-31 00:00:00.000', 'explicit numberformat 1000.00 explicit dateformat mm/dd/yy, no precision',          dateformat => 'mm/dd/yy', numberformat => '1000.00');
+is_dt('05/31/2014 2',           '2014-05-31 02:00:00.000', 'explicit numberformat 1000.00 explicit dateformat mm/dd/yy, precision hour',        dateformat => 'mm/dd/yy', numberformat => '1000.00');
+is_dt('05/31/2014 2:04',        '2014-05-31 02:04:00.000', 'explicit numberformat 1000.00 explicit dateformat mm/dd/yy, precision minute',      dateformat => 'mm/dd/yy', numberformat => '1000.00');
+is_dt('05/31/2014 2:04:59',     '2014-05-31 02:04:59.000', 'explicit numberformat 1000.00 explicit dateformat mm/dd/yy, precision second',      dateformat => 'mm/dd/yy', numberformat => '1000.00');
+is_dt('05/31/2014 02:4:59.098', '2014-05-31 02:04:59.098', 'explicit numberformat 1000.00 explicit dateformat mm/dd/yy, precision millisecond', dateformat => 'mm/dd/yy', numberformat => '1000.00');
+
+done_testing;
+
+1;