[Python-checkins] python/nondist/sandbox/datetime datetime.c,1.46,1.47 datetime.h,1.11,1.12 datetime.py,1.78,1.79 doc.txt,1.23,1.24 obj_date.c,1.36,1.37 obj_datetime.c,1.31,1.32 obj_time.c,1.1,1.2 test_both.py,1.48,1.49 test_datetime.py,1.55,1.56
tim_one@users.sourceforge.net
tim_one@users.sourceforge.net
Sat, 07 Dec 2002 10:34:41 -0800
- Previous message: [Python-checkins] python/nondist/sandbox/datetime obj_time.c,NONE,1.1 datetime.c,1.45,1.46 datetime.h,1.10,1.11 obj_datetime.c,1.30,1.31
- Next message: [Python-checkins] python/nondist/sandbox/datetime doc.txt,1.24,1.25
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /cvsroot/python/python/nondist/sandbox/datetime
In directory sc8-pr-cvs1:/tmp/cvs-serv21099
Modified Files:
datetime.c datetime.h datetime.py doc.txt obj_date.c
obj_datetime.c obj_time.c test_both.py test_datetime.py
Log Message:
Mounds of changes to implement the time type in C. Moved all the time
tests from test_datetime.py into test_both.py. More tests are needed
(e.g., for pickling of time objects -- this is implemented but not yet
tested).
The Python implementation had a fancy "pretty" __str__ for time and timetz.
I don't know whether or not that's a good idea, as people argue endlessly
over what "pretty" means. Since all the other types in this module with
an isoformat() method made __str__ a synonym, that's what I did here too,
and changed the Python implementation to match. I'm not married to this,
I just don't want to endure arguments about this now.
Pretty str() for all types or pretty str() for none is what I want to see,
the latter is quickest to implement, and if pretty is desired that's not
critical to get done before tha alpha release.
Index: datetime.c
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.c,v
retrieving revision 1.46
retrieving revision 1.47
diff -C2 -d -r1.46 -r1.47
*** datetime.c 7 Dec 2002 16:36:16 -0000 1.46
--- datetime.c 7 Dec 2002 18:34:39 -0000 1.47
***************
*** 46,56 ****
/* Time accessors for time. */
#define TIME_SET_HOUR(o, v) (PyDateTime_TIME_GET_HOUR(o) = (v))
#define TIME_SET_MINUTE(o, v) (PyDateTime_TIME_GET_MINUTE(o) = (v))
#define TIME_SET_SECOND(o, v) (PyDateTime_TIME_GET_SECOND(o) = (v))
#define TIME_SET_MICROSECOND(o, v) \
! (((o)->data[7] = ((v) & 0xff0000) >> 16), \
! ((o)->data[8] = ((v) & 0x00ff00) >> 8), \
! ((o)->data[9] = ((v) & 0x0000ff)))
/* Delta accessors for timedelta. */
--- 46,60 ----
/* Time accessors for time. */
+ #define TIME_GET_HOUR PyDateTime_TIME_GET_HOUR
+ #define TIME_GET_MINUTE PyDateTime_TIME_GET_MINUTE
+ #define TIME_GET_SECOND PyDateTime_TIME_GET_SECOND
+ #define TIME_GET_MICROSECOND PyDateTime_TIME_GET_MICROSECOND
#define TIME_SET_HOUR(o, v) (PyDateTime_TIME_GET_HOUR(o) = (v))
#define TIME_SET_MINUTE(o, v) (PyDateTime_TIME_GET_MINUTE(o) = (v))
#define TIME_SET_SECOND(o, v) (PyDateTime_TIME_GET_SECOND(o) = (v))
#define TIME_SET_MICROSECOND(o, v) \
! (((o)->data[3] = ((v) & 0xff0000) >> 16), \
! ((o)->data[4] = ((v) & 0x00ff00) >> 8), \
! ((o)->data[5] = ((v) & 0x0000ff)))
/* Delta accessors for timedelta. */
***************
*** 67,70 ****
--- 71,75 ----
static PyTypeObject PyDateTime_DateTimeType;
static PyTypeObject PyDateTime_DeltaType;
+ static PyTypeObject PyDateTime_TimeType;
/*
***************
*** 538,541 ****
--- 543,563 ----
}
+ /* Create a time instance with no range checking. */
+ static PyObject *
+ new_time(int hour, int minute, int second, int usecond)
+ {
+ PyDateTime_Time *self;
+
+ self = PyObject_New(PyDateTime_Time, &PyDateTime_TimeType);
+ if (self != NULL) {
+ self->hashcode = -1;
+ TIME_SET_HOUR(self, hour);
+ TIME_SET_MINUTE(self, minute);
+ TIME_SET_SECOND(self, second);
+ TIME_SET_MICROSECOND(self, usecond);
+ }
+ return (PyObject *) self;
+ }
+
/* Create a timedelta instance. Normalize the members iff normalize is
* true. Passing false is a speed optimization, if you know for sure
***************
*** 569,572 ****
--- 591,595 ----
static PyObject *date_unpickler_object = NULL;
static PyObject *datetime_unpickler_object = NULL;
+ static PyObject *time_unpickler_object = NULL;
/* For obscure reasons, we need to use tp_richcompare instead of tp_compare.
***************
*** 598,601 ****
--- 621,625 ----
#include "obj_date.c"
#include "obj_datetime.c"
+ #include "obj_time.c"
***************
*** 608,611 ****
--- 632,637 ----
{"_datetime_pickler", (PyCFunction)datetime_pickler, METH_O, NULL},
{"_datetime_unpickler", (PyCFunction)datetime_unpickler,METH_O, NULL},
+ {"_time_pickler", (PyCFunction)time_pickler, METH_O, NULL},
+ {"_time_unpickler", (PyCFunction)time_unpickler, METH_O, NULL},
{NULL, NULL}
};
***************
*** 630,633 ****
--- 656,661 ----
if (PyType_Ready(&PyDateTime_DeltaType) < 0)
return;
+ if (PyType_Ready(&PyDateTime_TimeType) < 0)
+ return;
/* timedelta values */
***************
*** 688,691 ****
--- 716,737 ----
Py_DECREF(dt);
+ /* time values */
+ d = PyDateTime_TimeType.tp_dict;
+
+ dt = new_time(0, 0, 0, 0);
+ if (dt == NULL || PyDict_SetItemString(d, "min", dt) < 0)
+ return;
+ Py_DECREF(dt);
+
+ dt = new_time(23, 59, 59, 999999);
+ if (dt == NULL || PyDict_SetItemString(d, "max", dt) < 0)
+ return;
+ Py_DECREF(dt);
+
+ dt = new_delta(0, 0, 1, 0);
+ if (dt == NULL || PyDict_SetItemString(d, "resolution", dt) < 0)
+ return;
+ Py_DECREF(dt);
+
Py_DECREF(safepickle);
***************
*** 695,707 ****
PyModule_AddIntConstant(m, "MINYEAR", MINYEAR);
PyModule_AddIntConstant(m, "MAXYEAR", MAXYEAR);
Py_INCREF(&PyDateTime_DateType);
! PyModule_AddObject(m, "date",
! (PyObject *) &PyDateTime_DateType);
Py_INCREF(&PyDateTime_DateTimeType);
PyModule_AddObject(m, "datetime",
(PyObject *) &PyDateTime_DateTimeType);
Py_INCREF(&PyDateTime_DeltaType);
! PyModule_AddObject(m, "timedelta",
! (PyObject *) &PyDateTime_DeltaType);
--- 741,757 ----
PyModule_AddIntConstant(m, "MINYEAR", MINYEAR);
PyModule_AddIntConstant(m, "MAXYEAR", MAXYEAR);
+
Py_INCREF(&PyDateTime_DateType);
! PyModule_AddObject(m, "date", (PyObject *) &PyDateTime_DateType);
!
Py_INCREF(&PyDateTime_DateTimeType);
PyModule_AddObject(m, "datetime",
(PyObject *) &PyDateTime_DateTimeType);
+
Py_INCREF(&PyDateTime_DeltaType);
! PyModule_AddObject(m, "timedelta", (PyObject *) &PyDateTime_DeltaType);
!
! Py_INCREF(&PyDateTime_TimeType);
! PyModule_AddObject(m, "time", (PyObject *) &PyDateTime_TimeType);
***************
*** 767,770 ****
--- 817,833 ----
pickler,
datetime_unpickler_object);
+ assert(temp);
+ Py_DECREF(temp);
+ Py_DECREF(pickler);
+
+ pickler = PyObject_GetAttrString(m, "_time_pickler");
+ assert(pickler);
+ time_unpickler_object = PyObject_GetAttrString(m,
+ "_time_unpickler");
+ assert(time_unpickler_object);
+ temp = PyObject_CallMethod(copyreg, "pickle", "OOO",
+ &PyDateTime_TimeType,
+ pickler,
+ time_unpickler_object);
assert(temp);
Py_DECREF(temp);
Index: datetime.h
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.h,v
retrieving revision 1.11
retrieving revision 1.12
diff -C2 -d -r1.11 -r1.12
*** datetime.h 7 Dec 2002 16:36:16 -0000 1.11
--- datetime.h 7 Dec 2002 18:34:39 -0000 1.12
***************
*** 21,31 ****
/* # of bytes for year, month, and day. */
! #define _PyDateTime_DATE_DATA_SIZE 4
!
! /* # of bytes for year, month, day, hour, minute, second, and usecond. */
! #define _PyDateTime_DATETIME_DATA_SIZE 10
/* # of bytes for hour, minute, second, and usecond. */
! #define _PyDateTime_TIME_DATA_SIZE 6
typedef struct
--- 21,31 ----
/* # of bytes for year, month, and day. */
! #define _PyDateTime_DATE_DATASIZE 4
/* # of bytes for hour, minute, second, and usecond. */
! #define _PyDateTime_TIME_DATASIZE 6
!
! /* # of bytes for year, month, day, hour, minute, second, and usecond. */
! #define _PyDateTime_DATETIME_DATASIZE 10
typedef struct
***************
*** 33,38 ****
PyObject_HEAD
long hashcode;
! unsigned char data[_PyDateTime_DATE_DATA_SIZE];
! } PyDateTime_Date;
typedef struct
--- 33,38 ----
PyObject_HEAD
long hashcode;
! unsigned char data[_PyDateTime_DATE_DATASIZE];
! } PyDateTime_Date;
typedef struct
***************
*** 40,45 ****
PyObject_HEAD
long hashcode;
! unsigned char data[_PyDateTime_DATETIME_DATA_SIZE];
! } PyDateTime_DateTime;
typedef struct
--- 40,45 ----
PyObject_HEAD
long hashcode;
! unsigned char data[_PyDateTime_DATETIME_DATASIZE];
! } PyDateTime_DateTime;
typedef struct
***************
*** 47,52 ****
PyObject_HEAD
long hashcode;
! unsigned char data[_PyDateTime_TIME_DATA_SIZE];
! } PyDateTime_Time;
typedef struct
--- 47,52 ----
PyObject_HEAD
long hashcode;
! unsigned char data[_PyDateTime_TIME_DATASIZE];
! } PyDateTime_Time;
typedef struct
Index: datetime.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.py,v
retrieving revision 1.78
retrieving revision 1.79
diff -C2 -d -r1.78 -r1.79
*** datetime.py 5 Dec 2002 19:45:03 -0000 1.78
--- datetime.py 7 Dec 2002 18:34:39 -0000 1.79
***************
*** 789,792 ****
--- 789,805 ----
self.__hour, self.__minute, s)
+ def isoformat(self):
+ """Return the time formatted according to ISO.
+
+ This is 'HH:MM:SS.mmmmmm'.
+ """
+ return "%02d:%02d:%02d.%06d" % (
+ self.__hour, self.__minute, self.__second,
+ self.__microsecond)
+
+ # XXX All other types in this module that define isoformat make __str__
+ # XXX a synonym, so for now I'm overriding this "pretty string" oddball
+ # XXX to do likewise. The last thing I need right now is to spend days
+ # XXX arguing about what "pretty" means in 6 distinct types <0.5 wink>.
def __str__(self):
"""Convert to pretty string, for str()."""
***************
*** 805,816 ****
return pretty
! def isoformat(self):
! """Return the time formatted according to ISO.
!
! This is 'HH:MM:SS.mmmmmm'.
! """
! return "%02d:%02d:%02d.%06d" % (
! self.__hour, self.__minute, self.__second,
! self.__microsecond)
def strftime(self, fmt):
--- 818,822 ----
return pretty
! __str__ = isoformat
def strftime(self, fmt):
***************
*** 937,947 ****
return s
- def __str__(self):
- """Convert to pretty string, for str()."""
- s = super(timetz, self).__str__()
- tz = self._tzstr()
- if tz: s = "%s %s" % (s, tz)
- return s
-
def isoformat(self):
"""Return the time formatted according to ISO.
--- 943,946 ----
***************
*** 953,956 ****
--- 952,965 ----
if tz: s += tz
return s
+
+ # XXX As for time, I'm making __str__ a synonym for isoformat for now.
+ def __str__(self):
+ """Convert to pretty string, for str()."""
+ s = super(timetz, self).__str__()
+ tz = self._tzstr()
+ if tz: s = "%s %s" % (s, tz)
+ return s
+
+ __str__ = isoformat
def strftime(self, fmt):
Index: doc.txt
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/doc.txt,v
retrieving revision 1.23
retrieving revision 1.24
diff -C2 -d -r1.23 -r1.24
*** doc.txt 7 Dec 2002 05:33:44 -0000 1.23
--- doc.txt 7 Dec 2002 18:34:39 -0000 1.24
***************
*** 503,506 ****
--- 503,567 ----
class time
==========
+ A time object represents an idealized time of day, independent of day
+ and timezone.
+
+ Constructor:
+
+ time(hour=0, minute=0, second=0, microsecond=0)
+
+ All arguments are optional. The may be ints or longs, in the
+ following ranges:
+
+ 0 <= hour < 24
+ 0 <= minute < 60
+ 0 <= second < 60
+ 0 <= microsecond < 1000000
+
+ If an argument outside those ranges is given, ValueError is raised.
+
+ Other constructors (class methods):
+
+ None
+
+ Class attributes:
+
+ .min
+ The earliest representable time, time(0, 0, 0).
+
+ .max
+ The latest representable time, time(23, 59, 59).
+
+ .resolution
+ The smallest possible difference between non-equal time
+ objects, timedelta(microseconds=1).
+
+ Instance attributes (read-only):
+
+ .hour in range(24)
+ .minute in range(60)
+ .second in range(60)
+ .microsecond in range(1000000)
+
+ Supported operations:
+
+ - comparison of time to time, where time1 is considered
+ less than time2 when time1 precedes time2 in time.
+
+ - hash, use as dict key
+
+ - pickling
+
+ Instance methods:
+
+ - isoformat()
+ Return a string representing the time in ISO 8601 format,
+ HH:MM:SS.mmmmmm
+ str(t) is equivalent to t.isoformat().
+
+ - strftime(format)
+ Return a string representing the time, controlled by an explicit
+ format string. Format codes for any fields other than hour, minute
+ and second should not be used, since a time object has meaningful
+ values only for those fields.
Index: obj_date.c
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/obj_date.c,v
retrieving revision 1.36
retrieving revision 1.37
diff -C2 -d -r1.36 -r1.37
*** obj_date.c 7 Dec 2002 03:12:57 -0000 1.36
--- obj_date.c 7 Dec 2002 18:34:39 -0000 1.37
***************
*** 365,369 ****
}
diff = memcmp(self->data, ((PyDateTime_Date *)other)->data,
! _PyDateTime_DATE_DATA_SIZE);
return diff_to_bool(diff, op);
}
--- 365,369 ----
}
diff = memcmp(self->data, ((PyDateTime_Date *)other)->data,
! _PyDateTime_DATE_DATASIZE);
return diff_to_bool(diff, op);
}
***************
*** 426,430 ****
{
return PyString_FromStringAndSize(self->data,
! _PyDateTime_DATE_DATA_SIZE);
}
--- 426,430 ----
{
return PyString_FromStringAndSize(self->data,
! _PyDateTime_DATE_DATASIZE);
}
***************
*** 436,445 ****
if (! PyString_Check(state) ||
! len != _PyDateTime_DATE_DATA_SIZE) {
PyErr_SetString(PyExc_TypeError,
"bad argument to date.__setstate__");
return NULL;
}
! memcpy(self->data, pdata, _PyDateTime_DATE_DATA_SIZE);
self->hashcode = -1;
--- 436,445 ----
if (! PyString_Check(state) ||
! len != _PyDateTime_DATE_DATASIZE) {
PyErr_SetString(PyExc_TypeError,
"bad argument to date.__setstate__");
return NULL;
}
! memcpy(self->data, pdata, _PyDateTime_DATE_DATASIZE);
self->hashcode = -1;
Index: obj_datetime.c
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/obj_datetime.c,v
retrieving revision 1.31
retrieving revision 1.32
diff -C2 -d -r1.31 -r1.32
*** obj_datetime.c 7 Dec 2002 16:36:16 -0000 1.31
--- obj_datetime.c 7 Dec 2002 18:34:39 -0000 1.32
***************
*** 446,450 ****
}
diff = memcmp(self->data, ((PyDateTime_DateTime *)other)->data,
! _PyDateTime_DATETIME_DATA_SIZE);
return diff_to_bool(diff, op);
}
--- 446,450 ----
}
diff = memcmp(self->data, ((PyDateTime_DateTime *)other)->data,
! _PyDateTime_DATETIME_DATASIZE);
return diff_to_bool(diff, op);
}
***************
*** 499,503 ****
{
return PyString_FromStringAndSize(self->data,
! _PyDateTime_DATETIME_DATA_SIZE);
}
--- 499,503 ----
{
return PyString_FromStringAndSize(self->data,
! _PyDateTime_DATETIME_DATASIZE);
}
***************
*** 509,518 ****
if (! PyString_Check(state) ||
! len != _PyDateTime_DATETIME_DATA_SIZE) {
PyErr_SetString(PyExc_TypeError,
"bad argument to datetime.__setstate__");
return NULL;
}
! memcpy(self->data, pdata, _PyDateTime_DATETIME_DATA_SIZE);
self->hashcode = -1;
--- 509,518 ----
if (! PyString_Check(state) ||
! len != _PyDateTime_DATETIME_DATASIZE) {
PyErr_SetString(PyExc_TypeError,
"bad argument to datetime.__setstate__");
return NULL;
}
! memcpy(self->data, pdata, _PyDateTime_DATETIME_DATASIZE);
self->hashcode = -1;
Index: obj_time.c
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/obj_time.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** obj_time.c 7 Dec 2002 16:36:16 -0000 1.1
--- obj_time.c 7 Dec 2002 18:34:39 -0000 1.2
***************
*** 1,5 ****
/*
* PyDateTime_Time implementation.
- * XXX This is currently a copy of obj_datetime.c, and unused.
*/
--- 1,4 ----
***************
*** 7,38 ****
static PyObject *
! datetime_hour(PyDateTime_DateTime *self, void *unused)
{
! return PyInt_FromLong(DATE_GET_HOUR(self));
}
static PyObject *
! datetime_minute(PyDateTime_DateTime *self, void *unused)
{
! return PyInt_FromLong(DATE_GET_MINUTE(self));
}
static PyObject *
! datetime_second(PyDateTime_DateTime *self, void *unused)
{
! return PyInt_FromLong(DATE_GET_SECOND(self));
}
static PyObject *
! datetime_microsecond(PyDateTime_DateTime *self, void *unused)
{
! return PyInt_FromLong(DATE_GET_MICROSECOND(self));
}
! static PyGetSetDef datetime_getset[] = {
! {"hour", (getter)datetime_hour},
! {"minute", (getter)datetime_minute},
! {"second", (getter)datetime_second},
! {"microsecond", (getter)datetime_microsecond},
{NULL}
};
--- 6,37 ----
static PyObject *
! time_hour(PyDateTime_Time *self, void *unused)
{
! return PyInt_FromLong(TIME_GET_HOUR(self));
}
static PyObject *
! time_minute(PyDateTime_Time *self, void *unused)
{
! return PyInt_FromLong(TIME_GET_MINUTE(self));
}
static PyObject *
! time_second(PyDateTime_Time *self, void *unused)
{
! return PyInt_FromLong(TIME_GET_SECOND(self));
}
static PyObject *
! time_microsecond(PyDateTime_Time *self, void *unused)
{
! return PyInt_FromLong(TIME_GET_MICROSECOND(self));
}
! static PyGetSetDef time_getset[] = {
! {"hour", (getter)time_hour},
! {"minute", (getter)time_minute},
! {"second", (getter)time_second},
! {"microsecond", (getter)time_microsecond},
{NULL}
};
***************
*** 41,50 ****
static PyObject *
! datetime_new(PyTypeObject *type, PyObject *args, PyObject *kw)
{
PyObject *self = NULL;
- long year;
- long month;
- long day;
long hour = 0;
long minute = 0;
--- 40,46 ----
static PyObject *
! time_new(PyTypeObject *type, PyObject *args, PyObject *kw)
{
PyObject *self = NULL;
long hour = 0;
long minute = 0;
***************
*** 53,78 ****
static char *keywords[] = {
! "year", "month", "day", "hour", "minute", "second",
! "microsecond", NULL
};
! if (PyArg_ParseTupleAndKeywords(args, kw, "lll|llll", keywords,
! &year, &month, &day, &hour, &minute,
! &second, &usecond)) {
! if (year < MINYEAR || year > MAXYEAR) {
! PyErr_SetString(PyExc_ValueError,
! "year is out of range");
! return NULL;
! }
! if (month < 1 || month > 12) {
! PyErr_SetString(PyExc_ValueError,
! "month must be in 1..12");
! return NULL;
! }
! if (day < 1 || day > days_in_month(year, month)) {
! PyErr_SetString(PyExc_ValueError,
! "day is out of range for month");
! return NULL;
! }
if (hour < 0 || hour > 23) {
PyErr_SetString(PyExc_ValueError,
--- 49,57 ----
static char *keywords[] = {
! "hour", "minute", "second", "microsecond", NULL
};
! if (PyArg_ParseTupleAndKeywords(args, kw, "|llll", keywords,
! &hour, &minute, &second, &usecond)) {
if (hour < 0 || hour > 23) {
PyErr_SetString(PyExc_ValueError,
***************
*** 95,430 ****
return NULL;
}
! self = new_datetime(year, month, day, hour, minute, second,
! usecond);
}
return self;
}
!
! /* TM_FUNC is the shared type of localtime() and gmtime(). */
! typedef struct tm *(*TM_FUNC)(const time_t *timer);
!
! static PyObject *
! datetime_from_timestamp(PyObject *cls, TM_FUNC f, double timestamp)
! {
! struct tm *tm;
! time_t timet = (time_t)timestamp;
! long us = (long)((timestamp - (double)timet) * 1e6);
! PyObject *result = NULL;
!
! tm = f(&timet);
! if (tm)
! result = PyObject_CallFunction(cls, "lllllll",
! tm->tm_year + 1900,
! tm->tm_mon + 1,
! tm->tm_mday,
! tm->tm_hour,
! tm->tm_min,
! tm->tm_sec,
! us);
! else
! PyErr_SetString(PyExc_ValueError,
! "timestamp out of range for "
! "platform localtime()/gmtime() function");
! return result;
! }
!
! /* Return new local datetime from timestamp (Python timestamp -- a double). */
! static PyObject *
! datetime_fromtimestamp(PyObject *self, PyObject *args)
! {
! PyObject *cls;
! double timestamp;
! PyObject *result = NULL;
!
! if (PyArg_ParseTuple(args, "Od:fromtimestamp", &cls, ×tamp))
! result = datetime_from_timestamp(cls, localtime, timestamp);
! return result;
! }
!
! /* Return new UTC datetime from timestamp (Python timestamp -- a double). */
! static PyObject *
! datetime_utcfromtimestamp(PyObject *self, PyObject *args)
! {
! PyObject *cls;
! double timestamp;
! PyObject *result = NULL;
!
! if (PyArg_ParseTuple(args, "Od:utcfromtimestamp", &cls, ×tamp))
! result = datetime_from_timestamp(cls, gmtime, timestamp);
! return result;
! }
!
! static PyObject *
! datetime_now(PyObject *self, PyObject *cls)
! {
! /* XXX MAJOR: This needs to get some notion of current time
! * XXX to better than 1-second resolution. Doing this in a x-
! * XXX platform way is mondo painful. Maybe floattime() from
! * XXX timemodule.c is good enough? We're running out of bits
! * XXX in a typical time_t, though, and gettimeofday() should do
! * XXX better than floattime() -- but gettimeofday isn't portable.
! */
! #if 0
! /* XXX need to create the instance by calling cls(y,mon,d,h,min,s,u) */
! struct timeval t;
! struct tm *tm;
! time_t timet;
!
! #ifdef GETTIMEOFDAY_NO_TZ
! gettimeofday(&t);
! #else /* !GETTIMEOFDAY_NO_TZ */
! gettimeofday(&t, (struct timezone *)NULL);
! #endif /* !GETTIMEOFDAY_NO_TZ */
! timet = t.tv_sec;
! tm = localtime(&timet);
!
! return PyObject_CallFunction(cls, "iiiiiil",
! tm->tm_year + 1900, tm->tm_mon + 1,
! tm->tm_mday, tm->tm_hour, tm->tm_min,
! tm->tm_sec, t.tv_usec);
! #else
! /* XXX need to create the instance by calling cls(y,mon,d,h,min,s,u) */
! struct tm *tm;
! time_t timet;
!
! time(&timet);
! tm = localtime(&timet);
!
! return PyObject_CallFunction(cls, "llllll",
! tm->tm_year + 1900, tm->tm_mon + 1,
! tm->tm_mday, tm->tm_hour, tm->tm_min,
! tm->tm_sec);
! #endif
! }
!
! static PyObject *
! datetime_utcnow(PyObject *self, PyObject *cls)
! {
! /* XXX Like datetime_now, this would like to do better than
! * XXX 1-second resolution.
! */
! struct tm *tm;
! time_t timet;
!
! time(&timet);
! tm = gmtime(&timet);
!
! return PyObject_CallFunction(cls, "llllll",
! tm->tm_year + 1900, tm->tm_mon + 1,
! tm->tm_mday, tm->tm_hour, tm->tm_min,
! tm->tm_sec);
! }
!
! /* datetime arithmetic. */
!
! /* Force all the datetime fields into range. The parameters are both
! * inputs and outputs. Returns < 0 on error.
! */
! static int
! normalize_datetime(long *year, long *month, long *day,
! long *hour, long *minute, long *second,
! long *microsecond)
! {
! normalize_pair(second, microsecond, 1000000);
! normalize_pair(minute, second, 60);
! normalize_pair(hour, minute, 60);
! normalize_pair(day, hour, 24);
! return normalize_date(year, month, day);
! }
!
! static PyObject *
! add_datetime_timedelta(PyDateTime_DateTime *date, PyDateTime_Delta *delta)
! {
! /* Note that the C-level additions can't overflow, because of
! * invariant bounds on the member values.
! */
! long year = GET_YEAR(date);
! long month = GET_MONTH(date);
! long day = GET_DAY(date) + GET_TD_DAYS(delta);
! long hour = DATE_GET_HOUR(date);
! long minute = DATE_GET_MINUTE(date);
! long second = DATE_GET_SECOND(date) + GET_TD_SECONDS(delta);
! long microsecond = DATE_GET_MICROSECOND(date) +
! GET_TD_MICROSECONDS(delta);
!
! if (normalize_datetime(&year, &month, &day,
! &hour, &minute, &second, µsecond) < 0)
! return NULL;
! else
! return new_datetime(year, month, day,
! hour, minute, second, microsecond);
! }
!
! static PyObject *
! sub_datetime_timedelta(PyDateTime_DateTime *date, PyDateTime_Delta *delta)
! {
! /* Note that the C-level subtractions can't overflow, because of
! * invariant bounds on the member values.
! */
! long year = GET_YEAR(date);
! long month = GET_MONTH(date);
! long day = GET_DAY(date) - GET_TD_DAYS(delta);
! long hour = DATE_GET_HOUR(date);
! long minute = DATE_GET_MINUTE(date);
! long second = DATE_GET_SECOND(date) - GET_TD_SECONDS(delta);
! long microsecond = DATE_GET_MICROSECOND(date) -
! GET_TD_MICROSECONDS(delta);
!
! if (normalize_datetime(&year, &month, &day,
! &hour, &minute, &second, µsecond) < 0)
! return NULL;
! else
! return new_datetime(year, month, day,
! hour, minute, second, microsecond);
! }
!
! static PyObject *
! sub_datetime_datetime(PyDateTime_DateTime *left, PyDateTime_DateTime *right)
! {
! long days1 = ymd_to_ord(GET_YEAR(left),
! GET_MONTH(left),
! GET_DAY(left));
! long days2 = ymd_to_ord(GET_YEAR(right),
! GET_MONTH(right),
! GET_DAY(right));
! /* These can't overflow, since the values are normalized. At most
! * this gives the number of seconds in one day.
! */
! long delta_s = (DATE_GET_HOUR(left) - DATE_GET_HOUR(right)) * 3600 +
! (DATE_GET_MINUTE(left) - DATE_GET_MINUTE(right)) * 60 +
! DATE_GET_SECOND(left) - DATE_GET_SECOND(right);
! long delta_us = DATE_GET_MICROSECOND(left) -
! DATE_GET_MICROSECOND(right);
!
! return new_delta(days1 - days2, delta_s, delta_us, 1);
! }
!
! static PyObject *
! datetime_add(PyObject *left, PyObject *right)
! {
! PyTypeObject *left_type = left->ob_type;
! PyTypeObject *right_type = right->ob_type;
!
! if (PyType_IsSubtype(left_type, &PyDateTime_DateTimeType)) {
! /* datetime + ??? */
! if (PyType_IsSubtype(right_type, &PyDateTime_DeltaType))
! /* datetime + delta */
! return add_datetime_timedelta(
! (PyDateTime_DateTime *)left,
! (PyDateTime_Delta *)right);
! }
! else if (PyType_IsSubtype(left_type, &PyDateTime_DeltaType)) {
! /* delta + datetime */
! return add_datetime_timedelta((PyDateTime_DateTime *) right,
! (PyDateTime_Delta *) left);
! }
! Py_INCREF(Py_NotImplemented);
! return Py_NotImplemented;
! }
!
! static PyObject *
! datetime_subtract(PyObject *left, PyObject *right)
! {
! PyTypeObject *left_type = left->ob_type;
! PyTypeObject *right_type = right->ob_type;
! PyObject *result = Py_NotImplemented;
!
! if (PyType_IsSubtype(left_type, &PyDateTime_DateTimeType)) {
! /* datetime - ??? */
! if (PyType_IsSubtype(right_type, &PyDateTime_DateTimeType)) {
! /* datetime - datetime */
! result = sub_datetime_datetime(
! (PyDateTime_DateTime *)left,
! (PyDateTime_DateTime *)right);
! }
! else if (PyType_IsSubtype(right_type, &PyDateTime_DeltaType)) {
! /* datetime - delta */
! result = sub_datetime_timedelta(
! (PyDateTime_DateTime *)left,
! (PyDateTime_Delta *)right);
! }
! }
!
! if (result == Py_NotImplemented)
! Py_INCREF(result);
! return result;
! }
!
! /* Various ways to turn a datetime into a string. */
static PyObject *
! datetime_repr(PyDateTime_DateTime *self)
{
! char buffer[1000];
char *typename = self->ob_type->tp_name;
! if (DATE_GET_MICROSECOND(self)) {
PyOS_snprintf(buffer, sizeof(buffer),
! "%s(%d, %d, %d, %d, %d, %d, %d)",
! typename,
! GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
! DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
! DATE_GET_SECOND(self),
! DATE_GET_MICROSECOND(self));
! }
! else if (DATE_GET_SECOND(self)) {
PyOS_snprintf(buffer, sizeof(buffer),
! "%s(%d, %d, %d, %d, %d, %d)",
! typename,
! GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
! DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
! DATE_GET_SECOND(self));
! }
! else {
PyOS_snprintf(buffer, sizeof(buffer),
! "%s(%d, %d, %d, %d, %d)",
! typename,
! GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
! DATE_GET_HOUR(self), DATE_GET_MINUTE(self));
! }
return PyString_FromString(buffer);
}
static PyObject *
! datetime_isoformat_helper(PyDateTime_DateTime *self, char sep)
{
char buffer[100];
! char *cp;
! cp = isoformat_date((PyDateTime_Date *)self, buffer, sizeof(buffer));
! assert(cp != NULL);
! *cp++ = sep;
! isoformat_time(self, cp, sizeof(buffer) - (cp - buffer));
return PyString_FromString(buffer);
}
static PyObject *
! datetime_str(PyDateTime_DateTime *self)
! {
! return datetime_isoformat_helper(self, ' ');
! }
!
! static PyObject *
! datetime_isoformat(PyDateTime_DateTime *self,
! PyObject *args, PyObject *kw)
{
! char sep = 'T';
! static char *keywords[] = {"sep", NULL};
!
! if (!PyArg_ParseTupleAndKeywords(args, kw, "|c:isoformat", keywords,
! &sep))
return NULL;
! return datetime_isoformat_helper(self, sep);
! }
!
! static PyObject *
! datetime_ctime(PyDateTime_DateTime *self)
! {
! return format_ctime((PyDateTime_Date *)self,
! DATE_GET_HOUR(self),
! DATE_GET_MINUTE(self),
! DATE_GET_SECOND(self));
}
--- 74,140 ----
return NULL;
}
! self = new_time(hour, minute, second, usecond);
}
return self;
}
! /* Various ways to turn a time into a string. */
static PyObject *
! time_repr(PyDateTime_Time *self)
{
! char buffer[100];
char *typename = self->ob_type->tp_name;
+ int h = TIME_GET_HOUR(self);
+ int m = TIME_GET_MINUTE(self);
+ int s = TIME_GET_SECOND(self);
+ int us = TIME_GET_MICROSECOND(self);
! if (us)
PyOS_snprintf(buffer, sizeof(buffer),
! "%s(%d, %d, %d, %d)", typename, h, m, s, us);
! else if (s)
PyOS_snprintf(buffer, sizeof(buffer),
! "%s(%d, %d, %d)", typename, h, m, s);
! else
PyOS_snprintf(buffer, sizeof(buffer),
! "%s(%d, %d)", typename, h, m);
return PyString_FromString(buffer);
}
+ /* time_isoformat is also tp_str */
static PyObject *
! time_isoformat(PyDateTime_Time *self)
{
char buffer[100];
! /* Reuse the time format code from the datetime type. */
! PyDateTime_DateTime datetime;
! PyDateTime_DateTime *pdatetime = &datetime;
! /* Copy over just the time bytes. */
! memcpy(pdatetime->data + _PyDateTime_DATE_DATASIZE,
! self->data,
! _PyDateTime_TIME_DATASIZE);
+ isoformat_time(pdatetime, buffer, sizeof(buffer));
return PyString_FromString(buffer);
}
static PyObject *
! time_strftime(PyDateTime_Time *self, PyObject *format)
{
! PyObject *result;
! PyObject *tuple = Py_BuildValue("iiiiiiiii",
! 0, 0, 0, /* year, month, day */
! TIME_GET_HOUR(self),
! TIME_GET_MINUTE(self),
! TIME_GET_SECOND(self),
! 0, 0, -1); /* weekday, daynum, dst */
! if (tuple == NULL)
return NULL;
! assert(PyTuple_Size(tuple) == 9);
! result = format_strftime(format, tuple);
! Py_DECREF(tuple);
! return result;
}
***************
*** 436,464 ****
*/
static PyObject *
! datetime_richcompare(PyDateTime_DateTime *self, PyObject *other, int op)
{
long diff;
! if (!PyType_IsSubtype(other->ob_type, &PyDateTime_DateTimeType)) {
PyErr_Format(PyExc_TypeError,
! "can't compare datetime to %s instance",
other->ob_type->tp_name);
return NULL;
}
! diff = memcmp(self->data, ((PyDateTime_DateTime *)other)->data,
! _PyDateTime_DATETIME_DATA_SIZE);
return diff_to_bool(diff, op);
}
static long
! datetime_hash(PyDateTime_DateTime *self)
{
if (self->hashcode == -1) {
PyObject *temp;
! temp = Py_BuildValue("lllllll", GET_YEAR(self),
! GET_MONTH(self), GET_DAY(self),
! DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
! DATE_GET_SECOND(self),
! DATE_GET_MICROSECOND(self));
if (temp != NULL) {
self->hashcode = PyObject_Hash(temp);
--- 146,174 ----
*/
static PyObject *
! time_richcompare(PyDateTime_Time *self, PyObject *other, int op)
{
long diff;
! if (!PyType_IsSubtype(other->ob_type, &PyDateTime_TimeType)) {
PyErr_Format(PyExc_TypeError,
! "can't compare time to %s instance",
other->ob_type->tp_name);
return NULL;
}
! diff = memcmp(self->data, ((PyDateTime_Time *)other)->data,
! _PyDateTime_TIME_DATASIZE);
return diff_to_bool(diff, op);
}
static long
! time_hash(PyDateTime_Time *self)
{
if (self->hashcode == -1) {
PyObject *temp;
! temp = Py_BuildValue("llll",
! TIME_GET_HOUR(self),
! TIME_GET_MINUTE(self),
! TIME_GET_SECOND(self),
! TIME_GET_MICROSECOND(self));
if (temp != NULL) {
self->hashcode = PyObject_Hash(temp);
***************
*** 469,495 ****
}
! static PyObject *
! datetime_timetuple(PyDateTime_DateTime *self)
! {
! const int year = GET_YEAR(self);
! const int month = GET_MONTH(self);
! const int day = GET_DAY(self);
!
! return Py_BuildValue("iiiiiiiii",
! year, month, day,
! DATE_GET_HOUR(self),
! DATE_GET_MINUTE(self),
! DATE_GET_SECOND(self),
! weekday(year, month, day),
! days_before_month(year, month) + day,
! -1);
! }
!
! static PyObject *
! datetime_getdate(PyDateTime_DateTime *self)
{
! return new_date((int)GET_YEAR(self),
! (int)GET_MONTH(self),
! (int)GET_DAY(self));
}
--- 179,189 ----
}
! static int
! time_nonzero(PyDateTime_Time *self)
{
! return TIME_GET_HOUR(self) ||
! TIME_GET_MINUTE(self) ||
! TIME_GET_SECOND(self) ||
! TIME_GET_MICROSECOND(self);
}
***************
*** 497,508 ****
static PyObject *
! datetime_getstate(PyDateTime_DateTime *self)
{
return PyString_FromStringAndSize(self->data,
! _PyDateTime_DATETIME_DATA_SIZE);
}
static PyObject *
! datetime_setstate(PyDateTime_DateTime *self, PyObject *state)
{
const int len = PyString_Size(state);
--- 191,202 ----
static PyObject *
! time_getstate(PyDateTime_Time *self)
{
return PyString_FromStringAndSize(self->data,
! _PyDateTime_TIME_DATASIZE);
}
static PyObject *
! time_setstate(PyDateTime_Time *self, PyObject *state)
{
const int len = PyString_Size(state);
***************
*** 510,519 ****
if (! PyString_Check(state) ||
! len != _PyDateTime_DATETIME_DATA_SIZE) {
PyErr_SetString(PyExc_TypeError,
! "bad argument to datetime.__setstate__");
return NULL;
}
! memcpy(self->data, pdata, _PyDateTime_DATETIME_DATA_SIZE);
self->hashcode = -1;
--- 204,213 ----
if (! PyString_Check(state) ||
! len != _PyDateTime_TIME_DATASIZE) {
PyErr_SetString(PyExc_TypeError,
! "bad argument to time.__setstate__");
return NULL;
}
! memcpy(self->data, pdata, _PyDateTime_TIME_DATASIZE);
self->hashcode = -1;
***************
*** 524,542 ****
/* XXX This seems a ridiculously inefficient way to pickle a short string. */
static PyObject *
! datetime_pickler(PyObject *module, PyDateTime_DateTime *datetime)
{
PyObject *state;
PyObject *result = NULL;
! if (datetime->ob_type != &PyDateTime_DateTimeType) {
PyErr_Format(PyExc_TypeError,
! "bad type passed to datetime pickler: %s",
! datetime->ob_type->tp_name);
return NULL;
}
! state = datetime_getstate(datetime);
if (state) {
result = Py_BuildValue("O(O)",
! datetime_unpickler_object,
state);
Py_DECREF(state);
--- 218,236 ----
/* XXX This seems a ridiculously inefficient way to pickle a short string. */
static PyObject *
! time_pickler(PyObject *module, PyDateTime_Time *time)
{
PyObject *state;
PyObject *result = NULL;
! if (time->ob_type != &PyDateTime_TimeType) {
PyErr_Format(PyExc_TypeError,
! "bad type passed to time pickler: %s",
! time->ob_type->tp_name);
return NULL;
}
! state = time_getstate(time);
if (state) {
result = Py_BuildValue("O(O)",
! time_unpickler_object,
state);
Py_DECREF(state);
***************
*** 546,562 ****
static PyObject *
! datetime_unpickler(PyObject *module, PyObject *arg)
{
! PyDateTime_DateTime *self;
if (! PyString_CheckExact(arg)) {
PyErr_Format(PyExc_TypeError,
! "bad type passed to datetime unpickler: %s",
arg->ob_type->tp_name);
return NULL;
}
! self = PyObject_New(PyDateTime_DateTime, &PyDateTime_DateTimeType);
if (self != NULL) {
! PyObject *res = datetime_setstate(self, arg);
Py_XDECREF(res);
}
--- 240,256 ----
static PyObject *
! time_unpickler(PyObject *module, PyObject *arg)
{
! PyDateTime_Time *self;
if (! PyString_CheckExact(arg)) {
PyErr_Format(PyExc_TypeError,
! "bad type passed to time unpickler: %s",
arg->ob_type->tp_name);
return NULL;
}
! self = PyObject_New(PyDateTime_Time, &PyDateTime_TimeType);
if (self != NULL) {
! PyObject *res = time_setstate(self, arg);
Py_XDECREF(res);
}
***************
*** 564,621 ****
}
! static PyMethodDef datetime_methods[] = {
! /* Class methods: */
! /* XXX METH_CLASS is implemented incorrectly:
! * XXX http://www.python.org/sf/548651
! * XXX The signatures of these methods will need to change (for
! * XXX the better) when that's fixed.
! */
! {"now", (PyCFunction)datetime_now,
! METH_O | METH_CLASS,
! "Return a new datetime representing local day and time."},
!
! {"utcnow", (PyCFunction)datetime_utcnow,
! METH_O | METH_CLASS,
! "Return a new datetime representing UTC day and time."},
!
! {"fromtimestamp", (PyCFunction)datetime_fromtimestamp,
! METH_VARARGS | METH_CLASS,
! "timestamp -> local datetime from a POSIX timestamp "
! "(like time.time())."},
!
! {"utcfromtimestamp", (PyCFunction)datetime_utcfromtimestamp,
! METH_VARARGS | METH_CLASS,
! "timestamp -> UTC datetime from a POSIX timestamp "
! "(like time.time())."},
!
! /* Instance methods: */
! {"timetuple", (PyCFunction)datetime_timetuple, METH_NOARGS,
! "Return time tuple, compatible with time.localtime()."},
!
! {"date", (PyCFunction)datetime_getdate, METH_NOARGS,
! "Return date object with same year, month and day."},
!
! {"ctime", (PyCFunction)datetime_ctime, METH_NOARGS,
! "Return ctime() style string."},
! {"isoformat", (PyCFunction)datetime_isoformat, METH_KEYWORDS,
! "[sep] -> string in ISO 8601 format, YYYY-MM-DDTHH:MM:SS.mmmmmm.\n\n"
! "sep is used to separate the year from the time, and defaults\n"
! "to 'T'."},
! {"__setstate__", (PyCFunction)datetime_setstate, METH_O,
PyDoc_STR("__setstate__(state)")},
! {"__getstate__", (PyCFunction)datetime_getstate, METH_NOARGS,
PyDoc_STR("__getstate__() -> state")},
{NULL, NULL}
};
! static char datetime_doc[] =
! "Basic date/time type.";
! static PyNumberMethods datetime_as_number = {
! datetime_add, /* nb_add */
! datetime_subtract, /* nb_subtract */
0, /* nb_multiply */
0, /* nb_divide */
--- 258,282 ----
}
! static PyMethodDef time_methods[] = {
! {"isoformat", (PyCFunction)time_isoformat, METH_KEYWORDS,
! "Return string in ISO 8601 format, HH:MM:SS.mmmmmm."},
! {"strftime", (PyCFunction)time_strftime, METH_O,
! "format -> strftime() style string."},
! {"__setstate__", (PyCFunction)time_setstate, METH_O,
PyDoc_STR("__setstate__(state)")},
! {"__getstate__", (PyCFunction)time_getstate, METH_NOARGS,
PyDoc_STR("__getstate__() -> state")},
{NULL, NULL}
};
! static char time_doc[] =
! "Basic time type.";
! static PyNumberMethods time_as_number = {
! 0, /* nb_add */
! 0, /* nb_subtract */
0, /* nb_multiply */
0, /* nb_divide */
***************
*** 626,638 ****
0, /* nb_positive */
0, /* nb_absolute */
! (inquiry)date_nonzero, /* nb_nonzero */
};
! statichere PyTypeObject PyDateTime_DateTimeType = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
/* XXX When this module is renamed to datetime, change tp_name. */
! "_datetime.datetime", /* tp_name */
! sizeof(PyDateTime_DateTime), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)PyObject_Del, /* tp_dealloc */
--- 287,299 ----
0, /* nb_positive */
0, /* nb_absolute */
! (inquiry)time_nonzero, /* nb_nonzero */
};
! statichere PyTypeObject PyDateTime_TimeType = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
/* XXX When this module is renamed to datetime, change tp_name. */
! "_datetime.time", /* tp_name */
! sizeof(PyDateTime_Time), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)PyObject_Del, /* tp_dealloc */
***************
*** 641,651 ****
0, /* tp_setattr */
0, /* tp_compare */
! (reprfunc)datetime_repr, /* tp_repr */
! &datetime_as_number, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
! (hashfunc)datetime_hash, /* tp_hash */
0, /* tp_call */
! (reprfunc)datetime_str, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
--- 302,312 ----
0, /* tp_setattr */
0, /* tp_compare */
! (reprfunc)time_repr, /* tp_repr */
! &time_as_number, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
! (hashfunc)time_hash, /* tp_hash */
0, /* tp_call */
! (reprfunc)time_isoformat, /* tp_str */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
***************
*** 653,667 ****
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
Py_TPFLAGS_BASETYPE, /* tp_flags */
! datetime_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
! (richcmpfunc)datetime_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
! datetime_methods, /* tp_methods */
0, /* tp_members */
! datetime_getset, /* tp_getset */
! &PyDateTime_DateType, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
--- 314,328 ----
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
Py_TPFLAGS_BASETYPE, /* tp_flags */
! time_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
! (richcmpfunc)time_richcompare, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
! time_methods, /* tp_methods */
0, /* tp_members */
! time_getset, /* tp_getset */
! 0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
***************
*** 670,675 ****
0, /* tp_init */
0, /* tp_alloc */
! datetime_new, /* tp_new */
_PyObject_Del, /* tp_free */
};
-
--- 331,335 ----
0, /* tp_init */
0, /* tp_alloc */
! time_new, /* tp_new */
_PyObject_Del, /* tp_free */
};
Index: test_both.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_both.py,v
retrieving revision 1.48
retrieving revision 1.49
diff -C2 -d -r1.48 -r1.49
*** test_both.py 7 Dec 2002 05:33:45 -0000 1.48
--- test_both.py 7 Dec 2002 18:34:39 -0000 1.49
***************
*** 40,43 ****
--- 40,44 ----
date = datetime.date
timedelta = datetime.timedelta
+ time = datetime.time
MINYEAR = datetime.MINYEAR
MAXYEAR = datetime.MAXYEAR
***************
*** 1119,1122 ****
--- 1120,1244 ----
# self.assertEqual(dt.time(), time(18, 45, 3, 1234))
+ class TestTime(unittest.TestCase):
+
+ theclass = time
+
+ def test_basic_attributes(self):
+ t = self.theclass(12, 0)
+ self.assertEqual(t.hour, 12)
+ self.assertEqual(t.minute, 0)
+ self.assertEqual(t.second, 0)
+ self.assertEqual(t.microsecond, 0)
+
+ def test_basic_attributes_nonzero(self):
+ # Make sure all attributes are non-zero so bugs in
+ # bit-shifting access show up.
+ t = self.theclass(12, 59, 59, 8000)
+ self.assertEqual(t.hour, 12)
+ self.assertEqual(t.minute, 59)
+ self.assertEqual(t.second, 59)
+ self.assertEqual(t.microsecond, 8000)
+
+ def test_roundtrip(self):
+ for t in (self.theclass(1, 2, 3, 4),):
+ # Verify t -> string -> time identity.
+ s = repr(t)
+ t2 = eval(s)
+ self.assertEqual(t, t2)
+
+ # Verify identity via reconstructing from pieces.
+ t2 = self.theclass(t.hour, t.minute, t.second,
+ t.microsecond)
+ self.assertEqual(t, t2)
+
+ def test_comparing(self):
+ t1 = self.theclass(9, 0, 0)
+ t2 = self.theclass(10, 0, 0)
+ t3 = self.theclass(9, 0, 0)
+ self.assertEqual(t1, t3)
+ self.assert_(t2 > t3)
+
+ def test_bad_constructor_arguments(self):
+ # bad hours
+ self.theclass(0, 0) # no exception
+ self.theclass(23, 0) # no exception
+ self.assertRaises(ValueError, self.theclass, -1, 0)
+ self.assertRaises(ValueError, self.theclass, 24, 0)
+ # bad minutes
+ self.theclass(23, 0) # no exception
+ self.theclass(23, 59) # no exception
+ self.assertRaises(ValueError, self.theclass, 23, -1)
+ self.assertRaises(ValueError, self.theclass, 23, 60)
+ # bad seconds
+ self.theclass(23, 59, 0) # no exception
+ self.theclass(23, 59, 59) # no exception
+ self.assertRaises(ValueError, self.theclass, 23, 59, -1)
+ self.assertRaises(ValueError, self.theclass, 23, 59, 60)
+ # bad microseconds
+ self.theclass(23, 59, 59, 0) # no exception
+ self.theclass(23, 59, 59, 999999) # no exception
+ self.assertRaises(ValueError, self.theclass, 23, 59, 59, -1)
+ self.assertRaises(ValueError, self.theclass, 23, 59, 59, 1000000)
+
+ def test_hash_equality(self):
+ d = self.theclass(23, 30, 17)
+ e = self.theclass(23, 30, 17)
+ self.assertEqual(d, e)
+ self.assertEqual(hash(d), hash(e))
+
+ dic = {d: 1}
+ dic[e] = 2
+ self.assertEqual(len(dic), 1)
+ self.assertEqual(dic[d], 2)
+ self.assertEqual(dic[e], 2)
+
+ d = self.theclass(0, 5, 17)
+ e = self.theclass(0, 5, 17)
+ self.assertEqual(d, e)
+ self.assertEqual(hash(d), hash(e))
+
+ dic = {d: 1}
+ dic[e] = 2
+ self.assertEqual(len(dic), 1)
+ self.assertEqual(dic[d], 2)
+ self.assertEqual(dic[e], 2)
+
+ def test_isoformat(self):
+ t = self.theclass(4, 5, 1, 123)
+ self.assertEqual(t.isoformat(), "04:05:01.000123")
+
+ def test_strftime(self):
+ t = self.theclass(1, 2, 3, 4)
+ self.assertEqual(t.strftime('%H %M %S'), "01 02 03")
+
+ def test_str(self):
+ self.assertEqual(str(self.theclass(1, 2, 3, 4)), "01:02:03.000004")
+ self.assertEqual(str(self.theclass(10, 2, 3, 4000)), "10:02:03.004000")
+ self.assertEqual(str(self.theclass(0, 2, 3, 400000)), "00:02:03.400000")
+ self.assertEqual(str(self.theclass(12, 2, 3, 0)), "12:02:03.000000")
+ self.assertEqual(str(self.theclass(23, 15, 0, 0)), "23:15:00.000000")
+
+ def test_repr(self):
+ name = self.theclass.__name__
+ if TESTING_C:
+ name = '_datetime.' + name
+
+ self.assertEqual(repr(self.theclass(1, 2, 3, 4)),
+ "%s(1, 2, 3, 4)" % name)
+ self.assertEqual(repr(self.theclass(10, 2, 3, 4000)),
+ "%s(10, 2, 3, 4000)" % name)
+ self.assertEqual(repr(self.theclass(0, 2, 3, 400000)),
+ "%s(0, 2, 3, 400000)" % name)
+ self.assertEqual(repr(self.theclass(12, 2, 3, 0)),
+ "%s(12, 2, 3)" % name)
+ self.assertEqual(repr(self.theclass(23, 15, 0, 0)),
+ "%s(23, 15)" % name)
+
+ def test_resolution_info(self):
+ self.assert_(isinstance(self.theclass.min, self.theclass))
+ self.assert_(isinstance(self.theclass.max, self.theclass))
+ self.assert_(isinstance(self.theclass.resolution, timedelta))
+ self.assert_(self.theclass.max > self.theclass.min)
+
def test_suite():
allsuites = [unittest.makeSuite(klass, 'test')
***************
*** 1126,1129 ****
--- 1248,1252 ----
TestDate,
TestDateTime,
+ TestTime,
)
]
Index: test_datetime.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/test_datetime.py,v
retrieving revision 1.55
retrieving revision 1.56
diff -C2 -d -r1.55 -r1.56
*** test_datetime.py 7 Dec 2002 05:33:45 -0000 1.55
--- test_datetime.py 7 Dec 2002 18:34:39 -0000 1.56
***************
*** 4,7 ****
--- 4,13 ----
"""
+ # XXX When a test passes in both the Python and C implementations, it
+ # XXX gets moved from this file into test_both.py.
+ # XXX Eventually (when the C implementation is complete), this file will
+ # XXX be empty, and at that time test_both.py will be renamed to
+ # XXX test_datetime.py.
+
import sys
import unittest
***************
*** 10,132 ****
MINYEAR, MAXYEAR
! class TestTime(unittest.TestCase):
!
! theclass = time
!
! def test_basic_attributes(self):
! t = self.theclass(12, 0)
! self.assertEqual(t.hour, 12)
! self.assertEqual(t.minute, 0)
! self.assertEqual(t.second, 0)
! self.assertEqual(t.microsecond, 0)
!
! def test_basic_attributes_nonzero(self):
! # Make sure all attributes are non-zero so bugs in
! # bit-shifting access show up.
! t = self.theclass(12, 59, 59, 8000)
! self.assertEqual(t.hour, 12)
! self.assertEqual(t.minute, 59)
! self.assertEqual(t.second, 59)
! self.assertEqual(t.microsecond, 8000)
!
! def test_roundtrip(self):
! for t in (self.theclass(1, 2, 3, 4),):
! # Verify t -> string -> time identity.
! s = repr(t)
! t2 = eval(s)
! self.assertEqual(t, t2)
!
! # Verify identity via reconstructing from pieces.
! t2 = self.theclass(t.hour, t.minute, t.second,
! t.microsecond)
! self.assertEqual(t, t2)
!
! def test_comparing(self):
! t1 = self.theclass(9, 0, 0)
! t2 = self.theclass(10, 0, 0)
! t3 = self.theclass(9, 0, 0)
! self.assertEqual(t1, t3)
! self.assert_(t2 > t3)
!
! def test_bad_constructor_arguments(self):
! # bad hours
! self.theclass(0, 0) # no exception
! self.theclass(23, 0) # no exception
! self.assertRaises(ValueError, self.theclass, -1, 0)
! self.assertRaises(ValueError, self.theclass, 24, 0)
! # bad minutes
! self.theclass(23, 0) # no exception
! self.theclass(23, 59) # no exception
! self.assertRaises(ValueError, self.theclass, 23, -1)
! self.assertRaises(ValueError, self.theclass, 23, 60)
! # bad seconds
! self.theclass(23, 59, 0) # no exception
! self.theclass(23, 59, 59) # no exception
! self.assertRaises(ValueError, self.theclass, 23, 59, -1)
! self.assertRaises(ValueError, self.theclass, 23, 59, 60)
! # bad microseconds
! self.theclass(23, 59, 59, 0) # no exception
! self.theclass(23, 59, 59, 999999) # no exception
! self.assertRaises(ValueError, self.theclass, 23, 59, 59, -1)
! self.assertRaises(ValueError, self.theclass, 23, 59, 59, 1000000)
!
! def test_hash_equality(self):
! d = self.theclass(23, 30, 17)
! e = self.theclass(23, 30, 17)
! self.assertEqual(d, e)
! self.assertEqual(hash(d), hash(e))
!
! dic = {d: 1}
! dic[e] = 2
! self.assertEqual(len(dic), 1)
! self.assertEqual(dic[d], 2)
! self.assertEqual(dic[e], 2)
!
! d = self.theclass(0, 5, 17)
! e = self.theclass(0, 5, 17)
! self.assertEqual(d, e)
! self.assertEqual(hash(d), hash(e))
!
! dic = {d: 1}
! dic[e] = 2
! self.assertEqual(len(dic), 1)
! self.assertEqual(dic[d], 2)
! self.assertEqual(dic[e], 2)
!
! def test_isoformat(self):
! t = self.theclass(4, 5, 1, 123)
! self.assertEqual(t.isoformat(), "04:05:01.000123")
!
! def test_strftime(self):
! t = self.theclass(1, 2, 3, 4)
! self.assertEqual(t.strftime('%H %M %S'), "01 02 03")
!
! def test_str(self):
! self.assertEqual(str(self.theclass(1, 2, 3, 4)), "1:02:03.000004")
! self.assertEqual(str(self.theclass(10, 2, 3, 4000)), "10:02:03.004")
! self.assertEqual(str(self.theclass(0, 2, 3, 400000)), "0:02:03.4")
! self.assertEqual(str(self.theclass(12, 2, 3, 0)), "12:02:03")
! self.assertEqual(str(self.theclass(23, 15, 0, 0)), "23:15")
!
! def test_repr(self):
! self.assertEqual(repr(self.theclass(1, 2, 3, 4)),
! "%s(1, 2, 3, 4)" % self.theclass.__name__)
! self.assertEqual(repr(self.theclass(10, 2, 3, 4000)),
! "%s(10, 2, 3, 4000)" % self.theclass.__name__)
! self.assertEqual(repr(self.theclass(0, 2, 3, 400000)),
! "%s(0, 2, 3, 400000)" % self.theclass.__name__)
! self.assertEqual(repr(self.theclass(12, 2, 3, 0)),
! "%s(12, 2, 3)" % self.theclass.__name__)
! self.assertEqual(repr(self.theclass(23, 15, 0, 0)),
! "%s(23, 15)" % self.theclass.__name__)
!
! def test_resolution_info(self):
! self.assert_(isinstance(self.theclass.min, self.theclass))
! self.assert_(isinstance(self.theclass.max, self.theclass))
! self.assert_(isinstance(self.theclass.resolution, timedelta))
! self.assert_(self.theclass.max > self.theclass.min)
!
!
! class TestTimeTZ(TestTime):
theclass = timetz
--- 16,20 ----
MINYEAR, MAXYEAR
! class TestTimeTZ(unittest.TestCase):
theclass = timetz
***************
*** 154,160 ****
self.assertEqual(t1, t3)
self.assertEqual(t2, t3)
! self.assertEqual(str(t1), "7:47 -05:00")
! self.assertEqual(str(t2), "12:47 +00:00")
! self.assertEqual(str(t3), "13:47 +01:00")
self.assertEqual(repr(t1), "timetz(7, 47, tzinfo=est)")
self.assertEqual(repr(t2), "timetz(12, 47, tzinfo=utc)")
--- 42,48 ----
self.assertEqual(t1, t3)
self.assertEqual(t2, t3)
! self.assertEqual(str(t1), "07:47:00.000000-05:00")
! self.assertEqual(str(t2), "12:47:00.000000+00:00")
! self.assertEqual(str(t3), "13:47:00.000000+01:00")
self.assertEqual(repr(t1), "timetz(7, 47, tzinfo=est)")
self.assertEqual(repr(t2), "timetz(12, 47, tzinfo=utc)")
***************
*** 266,274 ****
def test_suite():
- s3 = unittest.makeSuite(TestTime, 'test')
s4 = unittest.makeSuite(TestTimeTZ, 'test')
s5 = unittest.makeSuite(TestDateTime, 'test')
s6 = unittest.makeSuite(TestDateTimeTZ, 'test')
! return unittest.TestSuite([s3, s4, s5, s6])
def test_main():
--- 154,161 ----
def test_suite():
s4 = unittest.makeSuite(TestTimeTZ, 'test')
s5 = unittest.makeSuite(TestDateTime, 'test')
s6 = unittest.makeSuite(TestDateTimeTZ, 'test')
! return unittest.TestSuite([s4, s5, s6])
def test_main():
- Previous message: [Python-checkins] python/nondist/sandbox/datetime obj_time.c,NONE,1.1 datetime.c,1.45,1.46 datetime.h,1.10,1.11 obj_datetime.c,1.30,1.31
- Next message: [Python-checkins] python/nondist/sandbox/datetime doc.txt,1.24,1.25
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]