diff options
author | Paul "LeoNerd" Evans <leonerd@leonerd.org.uk> | 2012-02-01 19:19:51 +0000 |
---|---|---|
committer | Ævar Arnfjörð Bjarmason <avar@cpan.org> | 2012-02-11 22:22:25 +0000 |
commit | d3043e2c050ac9f2d11d4cb8c1470b3ce0241dc1 (patch) | |
tree | dee5c2fbc1701a45590e489a2e924c59bc040e0b | |
parent | 76e3b563bc78e0762abf833d7ad0f3f151a6860b (diff) | |
download | perl-d3043e2c050ac9f2d11d4cb8c1470b3ce0241dc1.tar.gz |
Yield -1 as undef from POSIX::strptime(); ensure that mktime() isn't biased by sec/min/hour = -1
-rw-r--r-- | ext/POSIX/POSIX.xs | 28 | ||||
-rw-r--r-- | ext/POSIX/t/time.t | 5 |
2 files changed, 23 insertions, 10 deletions
diff --git a/ext/POSIX/POSIX.xs b/ext/POSIX/POSIX.xs index 4ad3cce250..64fe3fb575 100644 --- a/ext/POSIX/POSIX.xs +++ b/ext/POSIX/POSIX.xs @@ -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 diff --git a/ext/POSIX/t/time.t b/ext/POSIX/t/time.t index bcd3b164fd..bbf2c50d9a 100644 --- a/ext/POSIX/t/time.t +++ b/ext/POSIX/t/time.t @@ -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'); |