diff --git a/DateTime-Format-Pg-0.16012-Fix-parse_duration-handling.patch b/DateTime-Format-Pg-0.16012-Fix-parse_duration-handling.patch new file mode 100644 index 0000000..17c29ca --- /dev/null +++ b/DateTime-Format-Pg-0.16012-Fix-parse_duration-handling.patch @@ -0,0 +1,146 @@ +From 3bf25ee812f8aecb018460ef943feeb003a73483 Mon Sep 17 00:00:00 2001 +From: Daisuke Maki +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ř +--- + 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 + diff --git a/perl-DateTime-Format-Pg.spec b/perl-DateTime-Format-Pg.spec index 446aa93..7cbb0f1 100644 --- a/perl-DateTime-Format-Pg.spec +++ b/perl-DateTime-Format-Pg.spec @@ -1,11 +1,15 @@ Name: perl-DateTime-Format-Pg Version: 0.16012 -Release: 1%{?dist} +Release: 2%{?dist} Summary: Parse and format PostgreSQL dates and times License: GPL+ or Artistic Group: Development/Libraries URL: http://search.cpan.org/dist/DateTime-Format-Pg/ Source0: http://search.cpan.org/CPAN/authors/id/D/DM/DMAKI/DateTime-Format-Pg-%{version}.tar.gz +# Support durations with fractional seconds again, bug #1377428, +# , in upstream +# after 0.16012 +Patch0: DateTime-Format-Pg-0.16012-Fix-parse_duration-handling.patch BuildArch: noarch # Build BuildRequires: perl @@ -39,6 +43,7 @@ it in a format accepted by PostgreSQL. %prep %setup -q -n DateTime-Format-Pg-%{version} +%patch0 -p1 %build perl Build.PL --installdirs=vendor @@ -58,6 +63,9 @@ perl Build.PL --installdirs=vendor %{_mandir}/man3/* %changelog +* Tue Sep 20 2016 Petr Pisar - 0.16012-2 +- Support durations with fractional seconds again (bug #1377428) + * Wed Jul 20 2016 Jitka Plesnikova - 0.16012-1 - 0.16012 bump