Skip Menu |

This queue is for tickets about the DateTime-Format-ISO8601 CPAN distribution.

Report information
The Basics
Id: 77535
Status: resolved
Priority: 0/
Queue: DateTime-Format-ISO8601

People
Owner: Nobody in particular
Requestors: zefram [...] fysh.org
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: "-00:00" isn't standard-conforming
Date: Wed, 30 May 2012 16:45:25 +0100
To: bug-DateTime-Format-ISO8601 [...] rt.cpan.org
From: Zefram <zefram [...] fysh.org>
DateTime::Format::ISO8601, when parsing, allows a zero timezone offset to be given with either sign: $ perl -MDateTime::Format::ISO8601 -lwe 'print +DateTime::Format::ISO8601->parse_datetime("2000-01-01T12:00:00+00:00")' 2000-01-01T12:00:00 $ perl -MDateTime::Format::ISO8601 -lwe 'print +DateTime::Format::ISO8601->parse_datetime("2000-01-01T12:00:00-00:00")' 2000-01-01T12:00:00 ISO 8601 actually only allows "+" here, not "-". See the explanation for the plus-or-minus sign in ISO 8601:2000 clause 5.1.1 or ISO 8601:2004 clause 3.4.2. The parsing function should reject "-" just as it rejects "!". -zefram
I agree that this is a bug. Do you have a patch or want to try a hand at adding tests for the problem? -Josh --
From: bitcard [...] chimpychompy.org
On Mon Jun 04 01:57:25 2012, JHOBLITT wrote: Show quoted text
> I agree that this is a bug. Do you have a patch or want to try a hand > at adding tests for the problem?
Tests and a possible fix attached. Not sure if this is the best way to address the issue, but it seemed easier than trying to reject a -ve tz offset in the regex.
Subject: rt77535.patch
diff -c -r DateTime-Format-ISO8601-0.08.orig/lib/DateTime/Format/ISO8601.pm DateTime-Format-ISO8601-0.08/lib/DateTime/Format/ISO8601.pm *** DateTime-Format-ISO8601-0.08.orig/lib/DateTime/Format/ISO8601.pm Sun Feb 12 06:44:53 2012 --- DateTime-Format-ISO8601-0.08/lib/DateTime/Format/ISO8601.pm Tue Jul 17 22:57:32 2012 *************** *** 112,118 **** ); # ISO8601 only allows years 0 to 9999 ! # this implimentation ignores the needs of expanded formats my $dt = DateTime->from_object( object => $args{ object } ); my $lower_bound = DateTime->new( year => 0 ); my $upper_bound = DateTime->new( year => 10000 ); --- 112,118 ---- ); # ISO8601 only allows years 0 to 9999 ! # this implementation ignores the needs of expanded formats my $dt = DateTime->from_object( object => $args{ object } ); my $lower_bound = DateTime->new( year => 0 ); my $upper_bound = DateTime->new( year => 10000 ); *************** *** 591,596 **** --- 591,597 ---- \&_add_month, \&_add_day, \&_normalize_offset, + \&_reject_negative_zero_offset, ], }, { *************** *** 605,610 **** --- 606,612 ---- \&_add_day, \&_fractional_second, \&_normalize_offset, + \&_reject_negative_zero_offset, ], }, *************** *** 620,625 **** --- 622,628 ---- \&_add_month, \&_add_day, \&_normalize_offset, + \&_reject_negative_zero_offset, ], }, { *************** *** 671,677 **** regex => qr/^ (\d{4}) -?? (\d\d) -?? (\d\d) T (\d\d) :?? (\d\d) :?? (\d\d) ([+-] \d\d :?? \d\d) $/x, params => [ qw( year month day hour minute second time_zone ) ], ! postprocess => \&_normalize_offset, }, { #YYYYMMDDThhmmss.ss[+-]hhmm 19850412T101530.5+0100 20041020T101530.5-0500 --- 674,680 ---- regex => qr/^ (\d{4}) -?? (\d\d) -?? (\d\d) T (\d\d) :?? (\d\d) :?? (\d\d) ([+-] \d\d :?? \d\d) $/x, params => [ qw( year month day hour minute second time_zone ) ], ! postprocess => [ \&_normalize_offset, \&_reject_negative_zero_offset ], }, { #YYYYMMDDThhmmss.ss[+-]hhmm 19850412T101530.5+0100 20041020T101530.5-0500 *************** *** 682,687 **** --- 685,691 ---- postprocess => [ \&_fractional_second, \&_normalize_offset, + \&_reject_negative_zero_offset, ], }, { *************** *** 693,698 **** --- 697,703 ---- postprocess => [ \&_fractional_second, \&_normalize_offset, + \&_reject_negative_zero_offset, ], }, *************** *** 703,709 **** regex => qr/^ (\d{4}) -?? (\d\d) -?? (\d\d) T (\d\d) :?? (\d\d) :?? (\d\d) ([+-] \d\d) $/x, params => [ qw( year month day hour minute second time_zone ) ], ! postprocess => \&_normalize_offset, }, { #YYYYMMDDThhmm 19850412T1015 --- 708,714 ---- regex => qr/^ (\d{4}) -?? (\d\d) -?? (\d\d) T (\d\d) :?? (\d\d) :?? (\d\d) ([+-] \d\d) $/x, params => [ qw( year month day hour minute second time_zone ) ], ! postprocess => [ \&_normalize_offset, \&_reject_negative_zero_offset ], }, { #YYYYMMDDThhmm 19850412T1015 *************** *** 732,738 **** regex => qr/^ (\d{4}) -?? W (\d\d) -?? (\d) T (\d\d) :?? (\d\d) ([+-] \d{2,4}) $/x, params => [ qw( year week day_of_year hour minute time_zone) ], ! postprocess => [ \&_normalize_week, \&_normalize_offset ], constructor => [ 'DateTime', 'from_day_of_year' ], }, ], --- 737,743 ---- regex => qr/^ (\d{4}) -?? W (\d\d) -?? (\d) T (\d\d) :?? (\d\d) ([+-] \d{2,4}) $/x, params => [ qw( year week day_of_year hour minute time_zone) ], ! postprocess => [ \&_normalize_week, \&_normalize_offset, \&_reject_negative_zero_offset ], constructor => [ 'DateTime', 'from_day_of_year' ], }, ], *************** *** 987,992 **** --- 992,1007 ---- return 1; } + sub _reject_negative_zero_offset { + my %p = @_; + + # Could check $p{input} but easier to check the normalized parsed + # version. + return if $p{ parsed }{ time_zone } =~ /^-0000$/; + + return 1; + } + 1; __END__ diff -c -r DateTime-Format-ISO8601-0.08.orig/t/06_bad_formats.t DateTime-Format-ISO8601-0.08/t/06_bad_formats.t *** DateTime-Format-ISO8601-0.08.orig/t/06_bad_formats.t Sun Feb 12 06:44:53 2012 --- DateTime-Format-ISO8601-0.08/t/06_bad_formats.t Tue Jul 17 22:59:27 2012 *************** *** 7,13 **** use lib qw( ./lib ); ! use Test::More tests => 4; use DateTime::Format::ISO8601; --- 7,13 ---- use lib qw( ./lib ); ! use Test::More tests => 30; use DateTime::Format::ISO8601; *************** *** 46,48 **** --- 46,94 ---- my $dt = $iso8601->parse_datetime( '20110704T205023+02:00' ); }; like( $@, qr/Invalid date format/ ); + + # -ve zero offset is invalid + # + # https://rt.cpan.org/Public/Bug/Display.html?id=77535 + + my @negative_zero_offsets = ( + "2001-01-01T12:00:00-00:00", + "2003-01-01T12:00:00-00", + '2004-04-12T10:15:30.5-00:00', + '20050412T101530.5-0000', + '20060412T101530-00', + '2007W155T1015-0000', + '2008-W15-5T10:15-00', + '080910-0000', + '08:09:10-00:00', + '080910-00', + '08:09:10-00', + '080910.5-0000', + '08:09:10.5-00:00', + ); + foreach ( @negative_zero_offsets ) { + eval { + my $dt = $iso8601->parse_datetime( $_ ); + }; + like ( $@, qr/Invalid date format/, "-ve zero offset $_" ); + } + + my @positive_zero_offsets = ( + "2000-01-01T12:00:00+00:00", + "2000-01-01T12:00:00+00", + '1985-04-12T10:15:30.5+00:00', + '19850412T101530.5+0000', + '19850412T101530+00', + '1985W155T1015+0000', + '1985-W15-5T10:15+00', + '080910+0000', + '08:09:10+00:00', + '080910+00', + '08:09:10+00', + '080910.5+0000', + '08:09:10.5+00:00', + ); + foreach ( @positive_zero_offsets ) { + my $dt = $iso8601->parse_datetime( $_ ); + ok ( $dt, "+ve zero offset $_" ); + }