parent
5eb6a3060c
commit
fc917d85cb
@ -1,146 +0,0 @@
|
||||
From 3bf25ee812f8aecb018460ef943feeb003a73483 Mon Sep 17 00:00:00 2001
|
||||
From: Daisuke Maki <lestrrat+github@gmail.com>
|
||||
Date: Fri, 19 Aug 2016 09:25:42 +0900
|
||||
Subject: [PATCH] Fix parse_duration handling
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
* handle fractional seconds (but only seconds)
|
||||
* if you want support for fractional [some other unit], please
|
||||
send in PRs with new tests
|
||||
|
||||
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||||
---
|
||||
README.md | 2 +-
|
||||
lib/DateTime/Format/Pg.pm | 58 +++++++++++++++++++++++++++++++----------------
|
||||
t/gh12.t | 20 ++++++++++++++++
|
||||
3 files changed, 59 insertions(+), 21 deletions(-)
|
||||
create mode 100644 t/gh12.t
|
||||
|
||||
diff --git a/README.md b/README.md
|
||||
index 7d1167f..6c61c27 100644
|
||||
--- a/README.md
|
||||
+++ b/README.md
|
||||
@@ -269,7 +269,7 @@ handled unambiguously by PostgreSQL.
|
||||
|
||||
If DateStyle is set to 'PostgreSQL', 'SQL', or 'German', PostgreSQL does
|
||||
not send numerical time zones for the TIMESTAMPTZ (or TIMESTAMP WITH
|
||||
-TIME ZONE) type. Unfortunatly, the time zone names used instead can be
|
||||
+TIME ZONE) type. Unfortunately, the time zone names used instead can be
|
||||
ambiguous: For example, 'EST' can mean -0500, +1000, or +1100.
|
||||
|
||||
You must set the 'server\_tz' variable to a time zone that is identical to that
|
||||
diff --git a/lib/DateTime/Format/Pg.pm b/lib/DateTime/Format/Pg.pm
|
||||
index b262e2a..0258cd7 100644
|
||||
--- a/lib/DateTime/Format/Pg.pm
|
||||
+++ b/lib/DateTime/Format/Pg.pm
|
||||
@@ -581,40 +581,58 @@ sub parse_duration {
|
||||
(my $string = $string_to_parse) =~ s/^@\s*//;
|
||||
$string =~ s/\+(\d+)/$1/g;
|
||||
|
||||
- my $subtract = 0;
|
||||
+ # Method used later on duration object
|
||||
+ my $arith_method = "add";
|
||||
if ( $string =~ s/ago// ) {
|
||||
- $subtract = 1;
|
||||
+ $arith_method = "subtract";
|
||||
}
|
||||
|
||||
my $sign = 0;
|
||||
my %done;
|
||||
|
||||
-# $timespec =~ s/\b(\d+):(\d\d):((\d\d)|(\d\d.\d+))\b/$1h $2m $3s/g;
|
||||
- $string =~ s/\b(\d+):(\d\d):(\d\d)\b/$1h $2m $3s/g;
|
||||
+ $string =~ s/\b(\d+):(\d\d):(\d\d)(\.\d+)?\b/$1h $2m $3$4s/g;
|
||||
$string =~ s/\b(\d+):(\d\d)\b/$1h $2m/g;
|
||||
$string =~ s/(-\d+h)\s+(\d+m)\s+(\d+s)\s*/$1 -$2 -$3 /;
|
||||
$string =~ s/(-\d+h)\s+(\d+m)\s*/$1 -$2 /;
|
||||
|
||||
while ($string =~ s/^\s*(-?\d+(?:[.,]\d+)?)\s*([a-zA-Z]+)(?:\s*(?:,|and)\s*)*//i) {
|
||||
my($amount, $unit) = ($1, $2);
|
||||
- $unit = lc($unit) unless length($unit) == 1;
|
||||
-
|
||||
- my ($base_unit, $num);
|
||||
- if ( defined( $units{$unit} ) ) {
|
||||
- ($base_unit, $num) = @{$units{$unit}};
|
||||
- my $key = $base_unit . "-" . $num;
|
||||
- Carp::croak "Unknown timespec: $string_to_parse" if defined($done{$key});
|
||||
- $done{$key} = 1;
|
||||
-
|
||||
- $amount =~ s/,/./;
|
||||
- if ( $subtract ) {
|
||||
- $du->subtract( $base_unit => $amount * $num );
|
||||
- } else {
|
||||
- $du->add( $base_unit => $amount * $num );
|
||||
+ if (length($unit) != 1) {
|
||||
+ $unit = lc($unit);
|
||||
+ }
|
||||
+
|
||||
+ my $udata = $units{$unit};
|
||||
+ if (! $udata) {
|
||||
+ Carp::croak("Unknown timespec: $string_to_parse");
|
||||
+ }
|
||||
+ my ($base_unit, $num) = @$udata;
|
||||
+ my $key = $base_unit . "-" . $num;
|
||||
+ if (exists $done{$key}) {
|
||||
+ Carp::croak("Unknown timespec: $string_to_parse");
|
||||
+ }
|
||||
+ $done{$key} = 1;
|
||||
+
|
||||
+ my @extra_args;
|
||||
+
|
||||
+ $amount =~ s/,/./;
|
||||
+ if ($amount =~ s/\.(\d+)$//) {
|
||||
+ my $fractional = $1;
|
||||
+ # We only handle fractional seconds right now. If you
|
||||
+ # need support for silly formats (from my perspective ;-P)
|
||||
+ # like '1.5 weeks', please provide me with a comprehensive
|
||||
+ # test for all possible combinations of fractional times.
|
||||
+ if ($base_unit ne "seconds") {
|
||||
+ Carp::croak("Fractional input detected: currently only fractional seconds are supported")
|
||||
}
|
||||
- } else {
|
||||
- Carp::croak "Unknown timespec: $string_to_parse";
|
||||
+
|
||||
+ # From the spec, Pg can take up to 6 digits for fractional part
|
||||
+ # (duh, as 1 sec = 1_000_000 nano sec). If we're missing 0's,
|
||||
+ # we should pad them
|
||||
+ $fractional .= '0'x (6 - length($fractional));
|
||||
+ push @extra_args, ("nanoseconds" => $fractional);
|
||||
}
|
||||
+
|
||||
+ $du->$arith_method($base_unit => $amount * $num, @extra_args);
|
||||
}
|
||||
|
||||
if ($string =~ /\S/) { # OK to have extra spaces, but nothing else
|
||||
diff --git a/t/gh12.t b/t/gh12.t
|
||||
new file mode 100644
|
||||
index 0000000..c4a2e83
|
||||
--- /dev/null
|
||||
+++ b/t/gh12.t
|
||||
@@ -0,0 +1,20 @@
|
||||
+use strict;
|
||||
+use Test::More;
|
||||
+
|
||||
+use_ok('DateTime::Format::Pg');
|
||||
+
|
||||
+# https://www.postgresql.org/docs/9.5/static/datatype-datetime.html#DATATYPE-INTERVAL-INPUT
|
||||
+my $offset = '1095 days 13:37:28.36922';
|
||||
+my $duration;
|
||||
+eval {
|
||||
+ $duration = DateTime::Format::Pg->parse_duration($offset);
|
||||
+};
|
||||
+my $e = $@;
|
||||
+if (! ok !$e, "should succeed parsing '$offset' without errors") {
|
||||
+ diag $e;
|
||||
+}
|
||||
+
|
||||
+is $duration->seconds, 28, "seconds should be '28'";
|
||||
+is $duration->nanoseconds, 369220, "seconds should be '369220'";
|
||||
+
|
||||
+done_testing;
|
||||
\ No newline at end of file
|
||||
--
|
||||
2.7.4
|
||||
|
Loading…
Reference in new issue