Yield -1 as undef from POSIX::strptime(); ensure that mktime() isn't biased by sec...
authorPaul "LeoNerd" Evans <leonerd@leonerd.org.uk>
Wed, 1 Feb 2012 19:19:51 +0000 (19:19 +0000)
committerÆvar Arnfjörð Bjarmason <avar@cpan.org>
Sat, 11 Feb 2012 22:22:25 +0000 (22:22 +0000)
ext/POSIX/POSIX.xs
ext/POSIX/t/time.t

index 4ad3cce..64fe3fb 100644 (file)
@@ -1908,20 +1908,30 @@ strptime(str, fmt, sec=-1, min=-1, hour=-1, mday=-1, mon=-1, year=-1, wday=-1, y
            }
 
            if(tm.tm_mday > -1 && tm.tm_mon > -1 && tm.tm_year > -1) {
+               /* if we leave sec/min/hour == -1, then these will be
+                * normalised to the previous day */
+               int was_sec  = tm.tm_sec;  tm.tm_sec  = 0;
+               int was_min  = tm.tm_min;  tm.tm_min  = 0;
+               int was_hour = tm.tm_hour; tm.tm_hour = 0;
+
                if(mktime(&tm) == (time_t)-1)
                    XSRETURN(0);
+
+               tm.tm_sec  = was_sec;
+               tm.tm_min  = was_min;
+               tm.tm_hour = was_hour;
            }
 
            EXTEND(SP, 9);
-           PUSHs(sv_2mortal(newSViv(tm.tm_sec)));
-           PUSHs(sv_2mortal(newSViv(tm.tm_min)));
-           PUSHs(sv_2mortal(newSViv(tm.tm_hour)));
-           PUSHs(sv_2mortal(newSViv(tm.tm_mday)));
-           PUSHs(sv_2mortal(newSViv(tm.tm_mon)));
-           PUSHs(sv_2mortal(newSViv(tm.tm_year)));
-           PUSHs(sv_2mortal(newSViv(tm.tm_wday)));
-           PUSHs(sv_2mortal(newSViv(tm.tm_yday)));
-           PUSHs(sv_2mortal(newSViv(tm.tm_isdst)));
+           PUSHs(tm.tm_sec  != -1 ? sv_2mortal(newSViv(tm.tm_sec))  : &PL_sv_undef);
+           PUSHs(tm.tm_min  != -1 ? sv_2mortal(newSViv(tm.tm_min))  : &PL_sv_undef);
+           PUSHs(tm.tm_hour != -1 ? sv_2mortal(newSViv(tm.tm_hour)) : &PL_sv_undef);
+           PUSHs(tm.tm_mday != -1 ? sv_2mortal(newSViv(tm.tm_mday)) : &PL_sv_undef);
+           PUSHs(tm.tm_mon  != -1 ? sv_2mortal(newSViv(tm.tm_mon))  : &PL_sv_undef);
+           PUSHs(tm.tm_year != -1 ? sv_2mortal(newSViv(tm.tm_year)) : &PL_sv_undef);
+           PUSHs(tm.tm_wday != -1 ? sv_2mortal(newSViv(tm.tm_wday)) : &PL_sv_undef);
+           PUSHs(tm.tm_yday != -1 ? sv_2mortal(newSViv(tm.tm_yday)) : &PL_sv_undef);
+           PUSHs(tm.tm_isdst!= -1 ? sv_2mortal(newSViv(tm.tm_isdst)): &PL_sv_undef);
        }
 
 void
index bcd3b16..bbf2c50 100644 (file)
@@ -4,7 +4,7 @@ use strict;
 
 use Config;
 use POSIX;
-use Test::More tests => 28;
+use Test::More tests => 29;
 
 # go to UTC to avoid DST issues around the world when testing.  SUS3 says that
 # null should get you UTC, but some environments want the explicit names.
@@ -74,6 +74,9 @@ is_deeply(\@time, [56, 34, 12, 18, 12-1, 2011-1900, 0, 351, 0], 'strptime() all
 @time = POSIX::strptime("2011-12-18", "%Y-%m-%d", 1, 23, 4);
 is_deeply(\@time, [1, 23, 4, 18, 12-1, 2011-1900, 0, 351, 0], 'strptime() all date fields with passed time');
 
+@time = POSIX::strptime("2011-12-18", "%Y-%m-%d");
+is_deeply(\@time, [undef, undef, undef, 18, 12-1, 2011-1900, 0, 351, 0], 'strptime() all date fields with no time');
+
 # tm_year == 6 => 1906, which is a negative time_t. Lets use 106 as 2006 instead
 @time = POSIX::strptime("12:34:56", "%H:%M:%S", 1, 2, 3, 4, 5, 106);
 is_deeply(\@time, [56, 34, 12, 4, 5, 106, 0, 154, 1], 'strptime() all time fields with passed date');