[Python-checkins] python/nondist/sandbox/datetime datetime.c,1.76,1.77 doc.txt,1.56,1.57 test_datetime.py,1.70,1.71
tim_one@users.sourceforge.net
tim_one@users.sourceforge.net
2002年12月15日 19:34:23 -0800
Update of /cvsroot/python/python/nondist/sandbox/datetime
In directory sc8-pr-cvs1:/tmp/cvs-serv22530
Modified Files:
datetime.c doc.txt test_datetime.py
Log Message:
Whew -- the C implementation of strftime is complete. Messy as hell,
but complete.
Index: datetime.c
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.c,v
retrieving revision 1.76
retrieving revision 1.77
diff -C2 -d -r1.76 -r1.77
*** datetime.c 16 Dec 2002 00:50:10 -0000 1.76
--- datetime.c 16 Dec 2002 03:34:20 -0000 1.77
***************
*** 766,771 ****
}
/* I sure don't want to reproduce the strftime code from the time module,
! * so this imports the module and calls it. Most of the hair is due to
* giving special meanings to the %z and %Z format codes via a preprocessing
* step on the format string.
--- 766,808 ----
}
+ /* Add an hours & minutes UTC offset string to buf. buf has no more than
+ * buflen bytes remaining. The UTC offset is gotten by calling
+ * tzinfo.uctoffset(tzinfoarg). If that returns None, 0円 is stored into
+ * *buf, and that's all. Else the returned value is checked for sanity (an
+ * integer in range), and if that's OK it's converted to an hours & minutes
+ * string of the form
+ * sign HH sep MM
+ * Returns 0 if everything is OK. If the return value from utcoffset() is
+ * bogus, an appropriate exception is set and -1 is returned.
+ */
+ static int
+ format_utcoffset(char *buf, int buflen, const char *sep,
+ PyObject *tzinfo, PyObject *tzinfoarg)
+ {
+ int offset;
+ int hours;
+ int minutes;
+ char sign;
+ int none;
+
+ offset = call_utcoffset(tzinfo, tzinfoarg, &none);
+ if (offset == -1 && PyErr_Occurred())
+ return -1;
+ if (none) {
+ *buf = '0円';
+ return 0;
+ }
+ sign = '+';
+ if (offset < 0) {
+ sign = '-';
+ offset = - offset;
+ }
+ hours = divmod(offset, 60, &minutes);
+ PyOS_snprintf(buf, buflen, "%c%02d%s%02d", sign, hours, sep, minutes);
+ return 0;
+ }
+
/* I sure don't want to reproduce the strftime code from the time module,
! * so this imports the module and calls it. All the hair is due to
* giving special meanings to the %z and %Z format codes via a preprocessing
* step on the format string.
***************
*** 774,790 ****
wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple)
{
! PyObject *time;
! PyObject *result;
assert(object && format && timetuple);
assert(PyString_Check(format));
! time = PyImport_ImportModule("time");
! if (time == NULL)
! return NULL;
! result = PyObject_CallMethod(time, "strftime", "OO",
! format, timetuple);
! Py_DECREF(time);
return result;
}
--- 811,976 ----
wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple)
{
! PyObject *result = NULL; /* guilty until proved innocent */
!
! PyObject *zreplacement = NULL; /* py string, replacement for %z */
! PyObject *Zreplacement = NULL; /* py string, replacement for %Z */
!
! char *pin; /* pointer to next char in input format */
! char ch; /* next char in input format */
!
! PyObject *newfmt = NULL; /* py string, the output format */
! char *pnew; /* pointer to available byte in output format */
! char totalnew; /* number bytes total in output format buffer,
! exclusive of trailing 0円 */
! char usednew; /* number bytes used so far in output format buffer */
!
! char *ptoappend; /* pointer to string to append to output buffer */
! int ntoappend; /* # of bytes to append to output buffer */
!
! char buf[100]; /* scratch buffer */
assert(object && format && timetuple);
assert(PyString_Check(format));
! /* Scan the input format, looking for %z and %Z escapes, building
! * a new format.
! */
! totalnew = PyString_Size(format); /* realistic if no %z/%Z */
! newfmt = PyString_FromStringAndSize(NULL, totalnew);
! if (newfmt == NULL) goto Done;
! pnew = PyString_AsString(newfmt);
! usednew = 0;
! pin = PyString_AsString(format);
! while ((ch = *pin++) != '0円') {
! if (ch != '%') {
! buf[0] = ch;
! ptoappend = buf;
! ntoappend = 1;
! goto Append;
! }
! if ((ch = *pin++) == '0円') {
! /* There's a lone trailing %; doesn't make sense. */
! PyErr_SetString(PyExc_ValueError, "strftime format "
! "ends with raw %");
! goto Done;
! }
! if (ch != 'z' && ch != 'Z') {
! buf[0] = '%';
! buf[1] = ch;
! ptoappend = buf;
! ntoappend = 2;
! goto Append;
! }
! if (ch == 'z') {
! if (zreplacement == NULL) {
! /* format utcoffset */
! PyObject *tzinfo = Py_None;
! zreplacement = PyString_FromString("");
! if (zreplacement == NULL) goto Done;
! if (PyDateTimeTZ_Check(object))
! tzinfo = ((PyDateTime_DateTimeTZ *)
! object)->tzinfo;
! else if (PyTimeTZ_Check(object))
! tzinfo = ((PyDateTime_TimeTZ *)
! object)->tzinfo;
! if (tzinfo != Py_None) {
! if (format_utcoffset(buf,
! (int)sizeof(buf),
! "",
! tzinfo,
! object) < 0)
! goto Done;
! Py_DECREF(zreplacement);
! zreplacement = PyString_FromString(buf);
! if (zreplacement == NULL) goto Done;
! }
! }
! assert(zreplacement != NULL);
! ptoappend = PyString_AsString(zreplacement);
! ntoappend = PyString_Size(zreplacement);
! goto Append;
! }
! assert(ch == 'Z');
! /* format tzname */
! if (Zreplacement == NULL) {
! Zreplacement = PyString_FromString("");
! if (Zreplacement == NULL) goto Done;
! if (PyObject_HasAttrString(object, "tzname")) {
! PyObject *temp;
! temp = PyObject_CallMethod(object, "tzname",
! "()");
! if (temp == NULL) goto Done;
! if (temp != Py_None && !PyString_Check(temp)) {
! PyErr_Format(PyExc_TypeError,
! "tzname() must return None "
! "or a string, not '%s'",
! temp->ob_type->tp_name);
! Py_DECREF(temp);
! goto Done;
! }
! if (temp != Py_None) {
! assert(PyString_Check(temp));
! /* Since the tzname is getting stuffed
! * into the format, we have to double
! * any % signs so that strftime
! * doesn't treat them as format
! * codes.
! */
! Py_DECREF(Zreplacement);
! Zreplacement = PyObject_CallMethod(
! temp,
! "replace",
! "ss",
! "%", "%%");
! Py_DECREF(temp);
! if (Zreplacement == NULL) goto Done;
! }
! else
! Py_DECREF(temp);
! }
! }
! assert(Zreplacement != NULL);
! ptoappend = PyString_AsString(Zreplacement);
! ntoappend = PyString_Size(Zreplacement);
!
! Append:
! /* Append the ntoappend chars starting at ptoappend to
! * the new format.
! */
! assert(ntoappend >= 0);
! if (ntoappend == 0)
! continue;
! while (usednew + ntoappend > totalnew) {
! int bigger = totalnew << 1;
! if ((bigger >> 1) != totalnew) { /* overflow */
! PyErr_NoMemory();
! goto Done;
! }
! if (_PyString_Resize(&newfmt, bigger) < 0)
! goto Done;
! totalnew = bigger;
! pnew = PyString_AsString(newfmt) + usednew;
! }
! memcpy(pnew, ptoappend, ntoappend);
! pnew += ntoappend;
! usednew += ntoappend;
! assert(usednew <= totalnew);
! } /* end while() */
!
! if (_PyString_Resize(&newfmt, usednew) < 0)
! goto Done;
! {
! PyObject *time = PyImport_ImportModule("time");
! if (time == NULL)
! goto Done;
! result = PyObject_CallMethod(time, "strftime", "OO",
! newfmt, timetuple);
! Py_DECREF(time);
! }
! Done:
! Py_XDECREF(zreplacement);
! Py_XDECREF(Zreplacement);
! Py_XDECREF(newfmt);
return result;
}
***************
*** 812,852 ****
if (us)
PyOS_snprintf(buffer + 8, bufflen - 8, ".%06d", us);
- }
-
- /* Add an hours & minutes UTC offset string to buf. buf has no more than
- * buflen bytes remaining. The UTC offset is gotten by calling
- * tzinfo.uctoffset(tzinfoarg). If that returns None, 0円 is stored into
- * *buf, and that's all. Else the returned value is checked for sanity (an
- * integer in range), and if that's OK it's converted to an hours & minutes
- * string of the form
- * sign HH sep MM
- * Returns 0 if everything is OK. If the return value from utcoffset() is
- * bogus, an appropriate exception is set and -1 is returned.
- */
- static int
- format_utcoffset(char *buf, int buflen, const char *sep,
- PyObject *tzinfo, PyObject *tzinfoarg)
- {
- int offset;
- int hours;
- int minutes;
- char sign;
- int none;
-
- offset = call_utcoffset(tzinfo, tzinfoarg, &none);
- if (offset == -1 && PyErr_Occurred())
- return -1;
- if (none) {
- *buf = '0円';
- return 0;
- }
- sign = '+';
- if (offset < 0) {
- sign = '-';
- offset = - offset;
- }
- hours = divmod(offset, 60, &minutes);
- PyOS_snprintf(buf, buflen, "%c%02d%s%02d", sign, hours, sep, minutes);
- return 0;
}
--- 998,1001 ----
Index: doc.txt
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/doc.txt,v
retrieving revision 1.56
retrieving revision 1.57
diff -C2 -d -r1.56 -r1.57
*** doc.txt 16 Dec 2002 00:25:34 -0000 1.56
--- doc.txt 16 Dec 2002 03:34:21 -0000 1.57
***************
*** 3,10 ****
- The Python implementation is missing docstrings in many places.
- - The custom %z and %Z format codes for timetz and datetimetz
- .strftime needs a C implementation (yuck). More generally,
- %z and %Z are plain busted in the C implementation.
-
- LaTeXize the docs.
--- 3,6 ----
***************
*** 14,17 ****
--- 10,18 ----
CLOSED
======
+ - The custom %z and %Z format codes for timetz and datetimetz
+ .strftime needs a C implementation (yuck). More generally,
+ %z and %Z are plain busted in the C implementation.
+ Done.
+
- datetimetz needs a C implementation. This seems "almost done". I
suspect I'm missing some untested method(s) still in the Python
Index: test_datetime.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v
retrieving revision 1.70
retrieving revision 1.71
diff -C2 -d -r1.70 -r1.71
*** test_datetime.py 16 Dec 2002 00:25:34 -0000 1.70
--- test_datetime.py 16 Dec 2002 03:34:21 -0000 1.71
***************
*** 13,18 ****
import unittest
- # XXX strftime is broken in the C implementation, when using %z or %Z.
-
# Import the right implementation, under name "datetime".
TESTING_C = 'c' in sys.argv
--- 13,16 ----