python mktime fails with overflow (same call works in other environments)
YONETANI Tomokazu
qhwt+dfly at les.ath.cx
Thu Sep 25 21:12:53 PDT 2008
On Thu, Sep 25, 2008 at 03:48:37PM -0500, Aran Cox wrote:
> It seems that if the TZ environment is set (I tested America/Chicago and
> GMT) the c/python/perl programs all work. If unset, (even though
> localtime exists, and corresponds to America/Chicago) all three
> programs fail to call mtime.
>
> I think may have been setting TZ and confused the issue slightly when
> testing the c and perl programs.
My timezone is set to JST and TZ is usually unset. And in fact
if I run the script with TZ set to America/Chicago, mktime() returned -1.
So I tried the C version with TZ=America/Chicago on a few machines which
also have the timezone set to JST:
FreeBSD 4.9-RELEASE: NG
FreeBSD 5.4-RELEASE: OK
According to FreeBSD CVSweb, FreeBSD 5.4-RELEASE has experienced
a vendor import of tzcode:
http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libc/stdtime/localtime.c?sortby=date#rev1.39
I think the essential part of the change that fixes mktime() is something
like attached to this message. I'm using patched libc on my -DEVELOPMENT
machine and it seems to work with TZ=America/Chicago now. But probably we
want to catch other fixes from FreeBSD.
Cheers.
--- localtime.c.orig 2008-08-28 12:26:09 +0900
+++ localtime.c 2008-09-26 12:52:26 +0900
@@ -1349,9 +1349,9 @@
}
static time_t
-time2(struct tm * const tmp,
+time2sub(struct tm * const tmp,
void (* const funcp)(const time_t *, long, struct tm *),
- const long offset, int * const okayp)
+ const long offset, int * const okayp, const int do_norm_secs)
{
const struct state * sp;
int dir;
@@ -1364,6 +1364,12 @@
*okayp = FALSE;
yourtm = *tmp;
+ if (do_norm_secs) {
+ if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
+ SECSPERMIN)) {
+ return WRONG;
+ }
+ }
if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
return WRONG;
if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
@@ -1493,6 +1499,23 @@
}
static time_t
+time2(struct tm * const tmp,
+ void (* const funcp)(const time_t *, long, struct tm *),
+ const long offset, int * const okayp)
+{
+ time_t t;
+
+ /*
+ ** First try without normalization of seconds
+ ** (in case tm_sec contains a value associated with a leap second).
+ ** If that fails, try with normalization of seconds.
+ */
+ t = time2sub(tmp, funcp, offset, okayp, FALSE);
+ return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE);
+}
+
+
+static time_t
time1(struct tm * const tmp,
void (* const funcp)(const time_t *, long, struct tm *),
const long offset)
More information about the Users
mailing list