Skip Menu |

This queue is for tickets about the POSIX-strptime CPAN distribution.

Report information
The Basics
Id: 46889
Status: resolved
Priority: 0/
Queue: POSIX-strptime

People
Owner: Nobody in particular
Requestors: djerius [...] cpan.org
Cc:
AdminCc:

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



Subject: Test failure on Solaris because of assumptions about intialization of tm structure
strptime.xs assumes that only relevant fields in the output tm structure are changed by strptime. This is the case on Linux, but is not the case on Solaris, which by default explicitly zeroes it. This causes the tests to fail on Solaris. The only "official" documentation on this behavior that I found while googling is here: http://www.opengroup.org/onlinepubs/009695399/functions/strptime.html where it states that: It is unspecified whether multiple calls to strptime() using the same tm structure will update the current contents of the structure or overwrite all contents of the structure. Conforming applications should make a single call to strptime() with a format and all data needed to completely specify the date and time being converted. This implies that Solaris' implementation is legitimate. I understand that strptime.xs is initializing tm with -1 in order to determine if a structure element was changed, but it looks like you're asking for more information than the standard will provide you, and to be portable across multiple platforms (currently the CPAN test matrix indicates that POSIX::strptime is only passing on Linux) you'll have to drop that behavior. Thanks, Diab
Hi there, I notice there hasn't been any activity on this bug in a year. I'll have a look at fixing it, and submit a patch. -- Paul Evans
On Fri Jun 12 12:36:30 2009, DJERIUS wrote: Show quoted text
> I understand that strptime.xs is initializing tm with -1 in order to > determine if a structure element was changed, but it looks like you're > asking for more information than the standard will provide you, and to > be portable across multiple platforms (currently the CPAN test matrix > indicates that POSIX::strptime is only passing on Linux) you'll have to > drop that behavior.
Try the attached patch, which makes the test insensitive to fields it doesn't explicitly expect to be set. If that works, I'll expand the patch out to fix up the docs and make the behaviour more explicit. -- Paul Evans
Subject: rt-46889.diff
--- t/POSIX-strptime.t 2010-07-16 13:17:24 +0000 +++ t/POSIX-strptime.t 2010-07-16 13:15:22 +0000 @@ -14,6 +14,10 @@ my @ret = POSIX::strptime($dstr, $fstr); + # Not all platforms guarantee to 'undef' out elements we didn't touch + # Only test on the elements it did + defined $target_ret[$_] or undef $ret[$_] for 0 .. $#target_ret; + is_deeply(\@ret, \@target_ret, $rec); } __DATA__
On Fri Jul 16 09:19:46 2010, PEVANS wrote: Show quoted text
> Try the attached patch, which makes the test insensitive to fields it > doesn't explicitly expect to be set. > > If that works, I'll expand the patch out to fix up the docs and make the > behaviour more explicit.
Which, apparently, it doesn't, because also some OSes don't set wday / yday correctly. Find attached a new patch that doesn't test around those; and also updates all the documentation. GOZER: Does this patch look good? Perhaps you could apply this upstream and version bump? -- Paul Evans
Subject: rt-46889.diff
=== modified file 'lib/POSIX/strptime.pm' --- lib/POSIX/strptime.pm 2010-07-16 13:17:24 +0000 +++ lib/POSIX/strptime.pm 2010-07-16 13:44:01 +0000 @@ -29,21 +29,38 @@ =head1 SYNOPSIS -($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = POSIX::strptime("string", "Format"); + ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = POSIX::strptime("string", "Format"); =head1 DESCRIPTION Perl interface to strptime(3) -=head1 METHODS +=head1 FUNCTIONS =over 4 =item strptime -($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = POSIX::strptime(string, format); - -Returns undef for any value not successfully extracted + ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = POSIX::strptime(string, format); + +The result for any value not extracted is not defined. Some platforms may +reliably return C<undef>, but this is dependent on the C<strptime(3)> function +in the underlying C library. + +For example, only the following fields may be relied upon: + + my ($min, $hour) = ( POSIX::strptime( "01:23", '%H:%M' ) )[1,2]; + + my ($mday, $mon, $year) = ( POSIX::strptime( "2010/07/16", '%Y/%m/%d' ) )[3,4,5]; + +Furthermore, not all platforms will set the C<$wday> and C<$yday> elements. If +these values are required, use C<mktime> and C<gmtime>: + + use POSIX qw( mktime ); + use POSIX::strptime qw( strptime ); + + my ($mday, $mon, $year) = ( POSIX::strptime( "2010/07/16", '%Y/%m/%d' ) )[3,4,5]; + my $wday = ( gmtime mktime 0, 0, 0, $mday, $mon, $year )[6]; =back === modified file 't/POSIX-strptime.t' --- t/POSIX-strptime.t 2010-07-16 13:17:24 +0000 +++ t/POSIX-strptime.t 2010-07-16 13:38:41 +0000 @@ -12,13 +12,17 @@ my @target_ret = map { $_ eq 'undef' ? undef : $_ } split(' ', $rstr); - my @ret = POSIX::strptime($dstr, $fstr); + my @ret = ( POSIX::strptime($dstr, $fstr) )[0..5]; + + # Not all platforms guarantee to 'undef' out elements we didn't touch + # Only test on the elements it did + defined $target_ret[$_] or undef $ret[$_] for 0 .. $#target_ret; is_deeply(\@ret, \@target_ret, $rec); } __DATA__ -2005-02-04 10:32:34 UTC|%F %T %Z|34 32 10 4 1 105 5 34 -2005-02-04 10:32:34 +0100|%F %T %z|34 32 10 4 1 105 5 34 -2005-02-04|%F|undef undef undef 4 1 105 5 34 +2005-02-04 10:32:34 UTC|%F %T %Z|34 32 10 4 1 105 +2005-02-04 10:32:34 +0100|%F %T %z|34 32 10 4 1 105 +2005-02-04|%F|undef undef undef 4 1 105 10:32:34|%H:%M:%S|34 32 10 undef undef undef undef undef blah blah|%H:%M:%S|undef undef undef undef undef undef undef undef
Thanks, will be included in POSIX-strptime 0.10, making its way to CPAN right now.