diff options
author | Guido van Rossum <guido@python.org> | 1998-08-25 14:51:12 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 1998-08-25 14:51:12 (GMT) |
commit | cfbaecc5468030bb3f17dbeb9e7afa1bf3363920 (patch) | |
tree | a99b4d90dd4f94f899c985aaf250b0cd238bf60f | |
parent | f5a80a4a8806fc293ac8de95ea6d304347af784e (diff) | |
download | cpython-cfbaecc5468030bb3f17dbeb9e7afa1bf3363920.zip cpython-cfbaecc5468030bb3f17dbeb9e7afa1bf3363920.tar.gz cpython-cfbaecc5468030bb3f17dbeb9e7afa1bf3363920.tar.bz2 |
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.
-rw-r--r-- | Modules/timemodule.c | 56 |
1 files changed, 37 insertions, 19 deletions
diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 7feefbc..7ad8a6f 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -112,6 +112,9 @@ extern int ftime(); static int floatsleep Py_PROTO((double)); static double floattime Py_PROTO(()); +/* For Y2K check */ +static PyObject *moddict; + #ifdef macintosh /* Our own timezone. We have enough information to deduce whether ** DST is on currently, but unfortunately we cannot put it to good @@ -322,8 +325,11 @@ gettmarg(args, p) PyObject *args; struct tm *p; { + int y; + memset((ANY *) p, '\0', sizeof(struct tm)); + if (!PyArg_Parse(args, "(iiiiiiiii)", - &p->tm_year, + &y, &p->tm_mon, &p->tm_mday, &p->tm_hour, @@ -333,8 +339,26 @@ gettmarg(args, p) &p->tm_yday, &p->tm_isdst)) return 0; - if (p->tm_year >= 1900) - p->tm_year -= 1900; + if (y < 1900) { + PyObject *accept = PyDict_GetItemString(moddict, + "accept2dyear"); + if (accept == NULL || !PyInt_Check(accept) || + PyInt_AsLong(accept) == 0) { + PyErr_SetString(PyExc_ValueError, + "year >= 1900 required"); + return 0; + } + if (69 <= y && y <= 99) + y += 1900; + else if (0 <= y && y <= 68) + y += 2000; + else { + PyErr_SetString(PyExc_ValueError, + "year out of range (00-99, 1900-*)"); + return 0; + } + } + p->tm_year = y - 1900; p->tm_mon--; p->tm_wday = (p->tm_wday + 1) % 7; p->tm_yday--; @@ -347,6 +371,7 @@ time_strftime(self, args) PyObject *self; PyObject *args; { + PyObject *tup; struct tm buf; const char *fmt; char *outbuf = 0; @@ -354,23 +379,8 @@ time_strftime(self, args) memset((ANY *) &buf, '\0', sizeof(buf)); - if (!PyArg_ParseTuple(args, "s(iiiiiiiii)", - &fmt, - &(buf.tm_year), - &(buf.tm_mon), - &(buf.tm_mday), - &(buf.tm_hour), - &(buf.tm_min), - &(buf.tm_sec), - &(buf.tm_wday), - &(buf.tm_yday), - &(buf.tm_isdst))) + if (!PyArg_ParseTuple(args, "sO", &fmt, &tup) || !gettmarg(tup, &buf)) return NULL; - if (buf.tm_year >= 1900) - buf.tm_year -= 1900; - buf.tm_mon--; - buf.tm_wday = (buf.tm_wday + 1) % 7; - buf.tm_yday--; /* I hate these functions that presume you know how big the output * will be ahead of time... */ @@ -414,6 +424,7 @@ time_strptime(self, args) PyErr_SetString(PyExc_ValueError, "invalid argument"); return NULL; } + memset((ANY *) &tm, '\0', sizeof(tm)); s = strptime(buf, fmt, &tm); if (s == NULL) { PyErr_SetString(PyExc_ValueError, "format mismatch"); @@ -595,6 +606,7 @@ void inittime() { PyObject *m, *d; + char *p; m = Py_InitModule3("time", time_methods, module_doc); d = PyModule_GetDict(m); #ifdef HAVE_TZNAME @@ -607,6 +619,12 @@ inittime() #endif ins(d, "daylight", PyInt_FromLong((long)daylight)); ins(d, "tzname", Py_BuildValue("(zz)", tzname[0], tzname[1])); + /* Accept 2-digit dates unless PYTHONY2K is set and non-empty */ + p = getenv("PYTHONY2K"); + ins(d, "accept2dyear", PyInt_FromLong((long) (!p || !*p))); + /* Squirrel away the module's dictionary for the y2k check */ + Py_INCREF(d); + moddict = d; #else /* !HAVE_TZNAME */ #if HAVE_TM_ZONE { |