Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit cfbaecc

Browse files
committed
Y2K fix affecting asctime(), mktime(), strftime().
2-digit years are now converted using rules that are (according to Fredrik Lundh) recommended by POSIX or X/Open: 0-68 mean 2000-2068, 69-99 mean 1969-1999. 2-digit years are now only accepted if time.accept2dyear is set to a nonzero integer; if it is zero or not an integer or absent, only year values >= 1900 are accepted. Year values 100-1899 and negative year values are never accepted. The initial value of time.accept2dyear depends on the environment variable PYTHONY2K: if PYTHONY2K is set and non-empty, time.accept2dyear is initialized to 0; if PYTHONY2K is empty or not set, time.accept2dyear is initialized to 0.
1 parent f5a80a4 commit cfbaecc

1 file changed

Lines changed: 37 additions & 19 deletions

File tree

Modules/timemodule.c

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,9 @@ extern int ftime();
112112
static int floatsleep Py_PROTO((double));
113113
static double floattime Py_PROTO(());
114114

115+
/* For Y2K check */
116+
static PyObject *moddict;
117+
115118
#ifdef macintosh
116119
/* Our own timezone. We have enough information to deduce whether
117120
** DST is on currently, but unfortunately we cannot put it to good
@@ -322,8 +325,11 @@ gettmarg(args, p)
322325
PyObject *args;
323326
struct tm *p;
324327
{
328+
int y;
329+
memset((ANY *) p, '\0', sizeof(struct tm));
330+
325331
if (!PyArg_Parse(args, "(iiiiiiiii)",
326-
&p->tm_year,
332+
&y,
327333
&p->tm_mon,
328334
&p->tm_mday,
329335
&p->tm_hour,
@@ -333,8 +339,26 @@ gettmarg(args, p)
333339
&p->tm_yday,
334340
&p->tm_isdst))
335341
return 0;
336-
if (p->tm_year >= 1900)
337-
p->tm_year -= 1900;
342+
if (y < 1900) {
343+
PyObject *accept = PyDict_GetItemString(moddict,
344+
"accept2dyear");
345+
if (accept == NULL || !PyInt_Check(accept) ||
346+
PyInt_AsLong(accept) == 0) {
347+
PyErr_SetString(PyExc_ValueError,
348+
"year >= 1900 required");
349+
return 0;
350+
}
351+
if (69 <= y && y <= 99)
352+
y += 1900;
353+
else if (0 <= y && y <= 68)
354+
y += 2000;
355+
else {
356+
PyErr_SetString(PyExc_ValueError,
357+
"year out of range (00-99, 1900-*)");
358+
return 0;
359+
}
360+
}
361+
p->tm_year = y - 1900;
338362
p->tm_mon--;
339363
p->tm_wday = (p->tm_wday + 1) % 7;
340364
p->tm_yday--;
@@ -347,30 +371,16 @@ time_strftime(self, args)
347371
PyObject *self;
348372
PyObject *args;
349373
{
374+
PyObject *tup;
350375
struct tm buf;
351376
const char *fmt;
352377
char *outbuf = 0;
353378
int i;
354379

355380
memset((ANY *) &buf, '\0', sizeof(buf));
356381

357-
if (!PyArg_ParseTuple(args, "s(iiiiiiiii)",
358-
&fmt,
359-
&(buf.tm_year),
360-
&(buf.tm_mon),
361-
&(buf.tm_mday),
362-
&(buf.tm_hour),
363-
&(buf.tm_min),
364-
&(buf.tm_sec),
365-
&(buf.tm_wday),
366-
&(buf.tm_yday),
367-
&(buf.tm_isdst)))
382+
if (!PyArg_ParseTuple(args, "sO", &fmt, &tup) || !gettmarg(tup, &buf))
368383
return NULL;
369-
if (buf.tm_year >= 1900)
370-
buf.tm_year -= 1900;
371-
buf.tm_mon--;
372-
buf.tm_wday = (buf.tm_wday + 1) % 7;
373-
buf.tm_yday--;
374384
/* I hate these functions that presume you know how big the output
375385
* will be ahead of time...
376386
*/
@@ -414,6 +424,7 @@ time_strptime(self, args)
414424
PyErr_SetString(PyExc_ValueError, "invalid argument");
415425
return NULL;
416426
}
427+
memset((ANY *) &tm, '\0', sizeof(tm));
417428
s = strptime(buf, fmt, &tm);
418429
if (s == NULL) {
419430
PyErr_SetString(PyExc_ValueError, "format mismatch");
@@ -595,6 +606,7 @@ void
595606
inittime()
596607
{
597608
PyObject *m, *d;
609+
char *p;
598610
m = Py_InitModule3("time", time_methods, module_doc);
599611
d = PyModule_GetDict(m);
600612
#ifdef HAVE_TZNAME
@@ -607,6 +619,12 @@ inittime()
607619
#endif
608620
ins(d, "daylight", PyInt_FromLong((long)daylight));
609621
ins(d, "tzname", Py_BuildValue("(zz)", tzname[0], tzname[1]));
622+
/* Accept 2-digit dates unless PYTHONY2K is set and non-empty */
623+
p = getenv("PYTHONY2K");
624+
ins(d, "accept2dyear", PyInt_FromLong((long) (!p || !*p)));
625+
/* Squirrel away the module's dictionary for the y2k check */
626+
Py_INCREF(d);
627+
moddict = d;
610628
#else /* !HAVE_TZNAME */
611629
#if HAVE_TM_ZONE
612630
{

0 commit comments

Comments
 (0)