[Python-checkins] python/nondist/sandbox/datetime obj_datetimetz.c,NONE,1.1 datetime.c,1.62,1.63 datetime.h,1.15,1.16 obj_date.c,1.48,1.49 obj_datetime.c,1.46,1.47

tim_one@users.sourceforge.net tim_one@users.sourceforge.net
2002年12月12日 17:13:49 -0800


Update of /cvsroot/python/python/nondist/sandbox/datetime
In directory sc8-pr-cvs1:/tmp/cvs-serv26152
Modified Files:
	datetime.c datetime.h obj_date.c obj_datetime.c 
Added Files:
	obj_datetimetz.c 
Log Message:
Added a non-functional C datetimetz implementation. It compiles and
the tests pass, but the new C type isn't really being used yet.
--- NEW FILE: obj_datetimetz.c ---
/* XXX This isn't functional yet, it merely compiles. It's a copy and
 * XXX very light edit of obj_datetime.c.
 */
/*
 * PyDateTime_DateTimeTZ implementation.
 */
/* Accessor properties. */
static PyObject *
datetimetz_hour(PyDateTime_DateTimeTZ *self, void *unused)
{
	return PyInt_FromLong(DATE_GET_HOUR(self));
}
static PyObject *
datetimetz_minute(PyDateTime_DateTimeTZ *self, void *unused)
{
	return PyInt_FromLong(DATE_GET_MINUTE(self));
}
static PyObject *
datetimetz_second(PyDateTime_DateTimeTZ *self, void *unused)
{
	return PyInt_FromLong(DATE_GET_SECOND(self));
}
static PyObject *
datetimetz_microsecond(PyDateTime_DateTimeTZ *self, void *unused)
{
	return PyInt_FromLong(DATE_GET_MICROSECOND(self));
}
static PyGetSetDef datetimetz_getset[] = {
	{"hour", (getter)datetimetz_hour},
	{"minute", (getter)datetimetz_minute},
	{"second", (getter)datetimetz_second},
	{"microsecond", (getter)datetimetz_microsecond},
	{NULL}
};
/* Constructors. */
static PyObject *
datetimetz_new(PyTypeObject *type, PyObject *args, PyObject *kw)
{
	PyObject *self = NULL;
	long year;
	long month;
	long day;
	long hour = 0;
	long minute = 0;
	long second = 0;
	long usecond = 0;
	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,
					"hour must be in 0..23");
			return NULL;
		}
		if (minute < 0 || minute > 59) {
			PyErr_SetString(PyExc_ValueError,
					"minute must be in 0..59");
			return NULL;
		}
		if (second < 0 || second > 59) {
			PyErr_SetString(PyExc_ValueError,
					"second must be in 0..59");
			return NULL;
		}
		if (usecond < 0 || usecond > 999999) {
			PyErr_SetString(PyExc_ValueError,
					"microsecond must be in 0..999999");
			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);
/* Internal helper.
 * Build datetime from a time_t and a distinct count of microseconds.
 * Pass localtime or gmtime for f, to control the interpretation of timet.
 */
static PyObject *
datetimetz_from_timet_and_us(PyObject *cls, TM_FUNC f, time_t timet, long us)
{
	struct tm *tm;
	PyObject *result = NULL;
	tm = f(&timet);
	if (tm)
		result = PyObject_CallFunction(cls, "iiiiiil",
					 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;
}
/* Internal helper.
 * Build datetime from a Python timestamp. Pass localtime or gmtime for f,
 * to control the interpretation of the timestamp. Since a double doesn't
 * have enough bits to cover a datetime's full range of precision, it's
 * better to call datetimetz_from_timet_and_us provided you have a way
 * to get that much precision (e.g., C time() isn't good enough).
 */
static PyObject *
datetimetz_from_timestamp(PyObject *cls, TM_FUNC f, double timestamp)
{
	time_t timet = (time_t)timestamp;
	long us = (long)((timestamp - (double)timet) * 1e6);
	return datetimetz_from_timet_and_us(cls, f, timet, us);
}
/* Internal helper.
 * Build most accurate possible datetime for current time. Pass localtime or
 * gmtime for f as appropriate.
 */
static PyObject *
datetimetz_best_possible(PyObject *cls, TM_FUNC f)
{
#ifdef HAVE_GETTIMEOFDAY
	struct timeval t;
#ifdef GETTIMEOFDAY_NO_TZ
	gettimeofday(&t);
#else
	gettimeofday(&t, (struct timezone *)NULL);
#endif
	return datetimetz_from_timet_and_us(cls, f, t.tv_sec, t.tv_usec);
#else	/* ! HAVE_GETTIMEOFDAY */
	/* No flavor of gettimeofday exists on this platform. Python's
	 * time.time() does a lot of other platform tricks to get the
	 * best time it can on the platform, and we're not going to do
	 * better than that (if we could, the better code would belong
	 * in time.time()!) We're limited by the precision of a double,
	 * though.
	 */
	PyObject *time;
	double dtime;
	time = time_time();
 	if (time == NULL)
 		return NULL;
	dtime = PyFloat_AsDouble(time);
	Py_DECREF(time);
	if (dtime == -1.0 && PyErr_Occurred())
		return NULL;
	return datetimetz_from_timestamp(cls, f, dtime);
#endif	/* ! HAVE_GETTIMEOFDAY */
}
/* Return new local datetime from timestamp (Python timestamp -- a double). */
static PyObject *
datetimetz_fromtimestamp(PyObject *cls, PyObject *args)
{
	double timestamp;
	PyObject *result = NULL;
	if (PyArg_ParseTuple(args, "d:fromtimestamp", &timestamp))
		result = datetimetz_from_timestamp(cls, localtime, timestamp);
	return result;
}
/* Return new UTC datetime from timestamp (Python timestamp -- a double). */
static PyObject *
datetimetz_utcfromtimestamp(PyObject *cls, PyObject *args)
{
	double timestamp;
	PyObject *result = NULL;
	if (PyArg_ParseTuple(args, "d:utcfromtimestamp", &timestamp))
		result = datetimetz_from_timestamp(cls, gmtime, timestamp);
	return result;
}
/* Return best possible local time -- this isn't constrained by the
 * precision of a timestamp.
 */
static PyObject *
datetimetz_now(PyObject *cls, PyObject *dummy)
{
	return datetimetz_best_possible(cls, localtime);
}
/* Return best possible UTC time -- this isn't constrained by the
 * precision of a timestamp.
 */
static PyObject *
datetimetz_utcnow(PyObject *cls, PyObject *dummy)
{
	return datetimetz_best_possible(cls, gmtime);
}
/* Return new datetime from date and time arguments. */
static PyObject *
datetimetz_combine(PyObject *cls, PyObject *args, PyObject *kw)
{
 	static char *keywords[] = {"date", "time", NULL};
	PyObject *date;
	PyObject *time;
	PyObject *result = NULL;
	if (PyArg_ParseTupleAndKeywords(args, kw, "O!O!:combine", keywords,
					&PyDateTime_DateType, &date,
					&PyDateTime_TimeType, &time))
		result = PyObject_CallFunction(cls, "iiiiiii",
						GET_YEAR(date),
				 		GET_MONTH(date),
						GET_DAY(date),
				 		TIME_GET_HOUR(time),
				 		TIME_GET_MINUTE(time),
				 		TIME_GET_SECOND(time),
				 		TIME_GET_MICROSECOND(time));
	return result;
}
/* datetime arithmetic. */
static PyObject *
add_datetimetz_timedelta(PyDateTime_DateTimeTZ *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, &microsecond) < 0)
		return NULL;
	else
		return new_datetime(year, month, day,
				 hour, minute, second, microsecond);
}
static PyObject *
sub_datetimetz_timedelta(PyDateTime_DateTimeTZ *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, &microsecond) < 0)
		return NULL;
	else
		return new_datetime(year, month, day,
				 hour, minute, second, microsecond);
}
static PyObject *
sub_datetimetz_datetime(PyDateTime_DateTimeTZ *left, PyDateTime_DateTimeTZ *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 *
datetimetz_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_datetimetz_timedelta(
					(PyDateTime_DateTimeTZ *)left,
					(PyDateTime_Delta *)right);
	}
	else if (PyType_IsSubtype(left_type, &PyDateTime_DeltaType)) {
		/* delta + datetime */
		return add_datetimetz_timedelta((PyDateTime_DateTimeTZ *) right,
					 (PyDateTime_Delta *) left);
	}
	Py_INCREF(Py_NotImplemented);
	return Py_NotImplemented;
}
static PyObject *
datetimetz_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_datetimetz_datetime(
					(PyDateTime_DateTimeTZ *)left,
					(PyDateTime_DateTimeTZ *)right);
		}
		else if (PyType_IsSubtype(right_type, &PyDateTime_DeltaType)) {
			/* datetime - delta */
			result = sub_datetimetz_timedelta(
					(PyDateTime_DateTimeTZ *)left,
					(PyDateTime_Delta *)right);
		}
	}
	if (result == Py_NotImplemented)
		Py_INCREF(result);
	return result;
}
/* Various ways to turn a datetime into a string. */
static PyObject *
datetimetz_repr(PyDateTime_DateTimeTZ *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 *
datetimetz_str(PyDateTime_DateTimeTZ *self)
{
	return PyObject_CallMethod((PyObject *)self, "isoformat", "(s)", " ");
}
static PyObject *
datetimetz_isoformat(PyDateTime_DateTimeTZ *self,
 PyObject *args, PyObject *kw)
{
	char sep = 'T';
	static char *keywords[] = {"sep", NULL};
	char buffer[100];
	char *cp;
	if (!PyArg_ParseTupleAndKeywords(args, kw, "|c:isoformat", keywords,
					 &sep))
		return NULL;
	cp = isoformat_date((PyDateTime_Date *)self, buffer, sizeof(buffer));
	assert(cp != NULL);
	*cp++ = sep;
	isoformat_time((PyDateTime_DateTime *)self,
		 cp,
		 sizeof(buffer) - (cp - buffer));
	return PyString_FromString(buffer);
}
static PyObject *
datetimetz_ctime(PyDateTime_DateTimeTZ *self)
{
	return format_ctime((PyDateTime_Date *)self,
			 DATE_GET_HOUR(self),
			 DATE_GET_MINUTE(self),
			 DATE_GET_SECOND(self));
}
/* Miscellaneous methods. */
/* This is more natural as a tp_compare, but doesn't work then: for whatever
 * reason, Python's try_3way_compare ignores tp_compare unless
 * PyInstance_Check returns true, but these aren't old-style classes.
 */
static PyObject *
datetimetz_richcompare(PyDateTime_DateTimeTZ *self, PyObject *other, int op)
{
	long diff;
	if (!PyType_IsSubtype(other->ob_type, &PyDateTime_DateTimeTZType)) {
		PyErr_Format(PyExc_TypeError,
			 "can't compare datetime to %s instance",
			 other->ob_type->tp_name);
		return NULL;
	}
	diff = memcmp(self->data, ((PyDateTime_DateTimeTZ *)other)->data,
		 _PyDateTime_DATETIME_DATASIZE);
	return diff_to_bool(diff, op);
}
static PyObject *datetimetz_getstate(PyDateTime_DateTimeTZ *self);
static long
datetimetz_hash(PyDateTime_DateTimeTZ *self)
{
	if (self->hashcode == -1) {
		PyObject *temp = datetimetz_getstate(self);
		if (temp != NULL) {
			self->hashcode = PyObject_Hash(temp);
			Py_DECREF(temp);
		}
	}
	return self->hashcode;
}
static PyObject *
datetimetz_timetuple(PyDateTime_DateTimeTZ *self)
{
	return build_struct_time(GET_YEAR(self),
				 GET_MONTH(self),
				 GET_DAY(self),
				 DATE_GET_HOUR(self),
				 DATE_GET_MINUTE(self),
				 DATE_GET_SECOND(self));
}
static PyObject *
datetimetz_getdate(PyDateTime_DateTimeTZ *self)
{
	return new_date(GET_YEAR(self),
			GET_MONTH(self),
			GET_DAY(self));
}
static PyObject *
datetimetz_gettime(PyDateTime_DateTimeTZ *self)
{
	return new_time(DATE_GET_HOUR(self),
			DATE_GET_MINUTE(self),
			DATE_GET_SECOND(self),
			DATE_GET_MICROSECOND(self));
}
/* Pickle support. Quite a maze! */
static PyObject *
datetimetz_getstate(PyDateTime_DateTimeTZ *self)
{
	return PyString_FromStringAndSize(self->data,
					 _PyDateTime_DATETIME_DATASIZE);
}
static PyObject *
datetimetz_setstate(PyDateTime_DateTimeTZ *self, PyObject *state)
{
	const int len = PyString_Size(state);
	unsigned char *pdata = (unsigned char*)PyString_AsString(state);
	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;
	Py_INCREF(Py_None);
	return Py_None;
}
/* XXX This seems a ridiculously inefficient way to pickle a short string. */
static PyObject *
datetimetz_pickler(PyObject *module, PyDateTime_DateTimeTZ *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 = datetimetz_getstate(datetime);
	if (state) {
		result = Py_BuildValue("O(O)",
				 datetimetz_unpickler_object,
				 state);
		Py_DECREF(state);
	}
	return result;
}
static PyObject *
datetimetz_unpickler(PyObject *module, PyObject *arg)
{
	PyDateTime_DateTimeTZ *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_DateTimeTZ, &PyDateTime_DateTimeType);
	if (self != NULL) {
		PyObject *res = datetimetz_setstate(self, arg);
		if (res == NULL) {
			Py_DECREF(self);
			return NULL;
		}
		Py_DECREF(res);
	}
	return (PyObject *)self;
}
static PyMethodDef datetimetz_methods[] = {
	/* Class methods: */
	{"now", (PyCFunction)datetimetz_now,
	 METH_NOARGS | METH_CLASS,
	 PyDoc_STR("Return a new datetime representing local day and time.")},
	{"utcnow", (PyCFunction)datetimetz_utcnow,
	 METH_NOARGS | METH_CLASS,
	 PyDoc_STR("Return a new datetime representing UTC day and time.")},
	{"fromtimestamp", (PyCFunction)datetimetz_fromtimestamp,
	 METH_VARARGS | METH_CLASS,
	 PyDoc_STR("timestamp -> local datetime from a POSIX timestamp "
	 	 "(like time.time()).")},
	{"utcfromtimestamp", (PyCFunction)datetimetz_utcfromtimestamp,
	 METH_VARARGS | METH_CLASS,
	 PyDoc_STR("timestamp -> UTC datetime from a POSIX timestamp "
	 	 "(like time.time()).")},
	{"combine", (PyCFunction)datetimetz_combine,
	 METH_VARARGS | METH_KEYWORDS | METH_CLASS,
	 PyDoc_STR("date, time -> datetime with same date and time fields")},
	/* Instance methods: */
	{"timetuple", (PyCFunction)datetimetz_timetuple, METH_NOARGS,
 PyDoc_STR("Return time tuple, compatible with time.localtime().")},
	{"date", (PyCFunction)datetimetz_getdate, METH_NOARGS,
 PyDoc_STR("Return date object with same year, month and day.")},
	{"time", (PyCFunction)datetimetz_gettime, METH_NOARGS,
 PyDoc_STR("Return time object with same hour, minute, second and "
 	 "microsecond.")},
	{"ctime", (PyCFunction)datetimetz_ctime,	METH_NOARGS,
	 PyDoc_STR("Return ctime() style string.")},
	{"isoformat", (PyCFunction)datetimetz_isoformat, METH_KEYWORDS,
	 PyDoc_STR("[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)datetimetz_setstate, METH_O,
	 PyDoc_STR("__setstate__(state)")},
	{"__getstate__", (PyCFunction)datetimetz_getstate, METH_NOARGS,
	 PyDoc_STR("__getstate__() -> state")},
	{NULL,	NULL}
};
static char datetimetz_doc[] =
PyDoc_STR("date/time type.");
static PyNumberMethods datetimetz_as_number = {
	datetimetz_add,				/* nb_add */
	datetimetz_subtract,			/* nb_subtract */
	0,					/* nb_multiply */
	0,					/* nb_divide */
	0,					/* nb_remainder */
	0,					/* nb_divmod */
	0,					/* nb_power */
	0,					/* nb_negative */
	0,					/* nb_positive */
	0,					/* nb_absolute */
	0,					/* nb_nonzero */
};
statichere PyTypeObject PyDateTime_DateTimeTZType = {
	PyObject_HEAD_INIT(NULL)
	0,					/* ob_size */
	/* XXX When this module is renamed to datetime, change tp_name. */
	"_datetime.datetimetz",			/* tp_name */
	sizeof(PyDateTime_DateTimeTZ),		/* tp_basicsize */
	0,					/* tp_itemsize */
	(destructor)PyObject_Del,		/* tp_dealloc */
	0,					/* tp_print */
	0,					/* tp_getattr */
	0,					/* tp_setattr */
	0,					/* tp_compare */
	(reprfunc)datetimetz_repr,		/* tp_repr */
	&datetimetz_as_number,			/* tp_as_number */
	0,					/* tp_as_sequence */
	0,					/* tp_as_mapping */
	(hashfunc)datetimetz_hash,		/* tp_hash */
	0, 			/* tp_call */
	(reprfunc)datetimetz_str,		/* tp_str */
	PyObject_GenericGetAttr,		/* tp_getattro */
	0,					/* tp_setattro */
	0,					/* tp_as_buffer */
	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
 Py_TPFLAGS_BASETYPE,			/* tp_flags */
	datetimetz_doc,				/* tp_doc */
	0,					/* tp_traverse */
	0,					/* tp_clear */
	(richcmpfunc)datetimetz_richcompare,	/* tp_richcompare */
	0,					/* tp_weaklistoffset */
	0,					/* tp_iter */
	0,					/* tp_iternext */
	datetimetz_methods,			/* tp_methods */
	0,					/* tp_members */
	datetimetz_getset,			/* tp_getset */
	&PyDateTime_DateTimeType,		/* tp_base */
	0,					/* tp_dict */
	0,					/* tp_descr_get */
	0,					/* tp_descr_set */
	0,					/* tp_dictoffset */
	0,					/* tp_init */
	0,					/* tp_alloc */
	datetimetz_new,				/* tp_new */
	_PyObject_Del,				/* tp_free */
};
Index: datetime.c
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.c,v
retrieving revision 1.62
retrieving revision 1.63
diff -C2 -d -r1.62 -r1.63
*** datetime.c	12 Dec 2002 22:08:22 -0000	1.62
--- datetime.c	13 Dec 2002 01:13:46 -0000	1.63
***************
*** 70,73 ****
--- 70,74 ----
 static PyTypeObject PyDateTime_DateType;
 static PyTypeObject PyDateTime_DateTimeType;
+ static PyTypeObject PyDateTime_DateTimeTZType;
 static PyTypeObject PyDateTime_DeltaType;
 static PyTypeObject PyDateTime_TimeType;
***************
*** 404,434 ****
 }
 
- /* Fiddle days (d), seconds (s), and microseconds (us) so that
- * 	0 <= *s < 24*3600
- * 	0 <= *us < 1000000
- * The input values must be such that the internals don't overflow.
- * The way this routine is used, we don't get close.
- */
- static void
- normalize_d_s_us(long *d, long *s, long *us)
- {
- 	if (*us < 0 || *us >= 1000000) {
- 		normalize_pair(s, us, 1000000);
- 		/* |s| can't be bigger than about
- 		 * |original s| + |original us|/1000000 now.
- 		 */
- 
- 	}
- 	if (*s < 0 || *s >= 24*3600) {
- 		normalize_pair(d, s, 24*3600);
- 		/* |d| can't be bigger than about
- 		 * |original d| +
- 		 * (|original s| + |original us|/1000000) / (24*3600) now.
- 		 */
- 	}
- 	assert(0 <= *s && *s < 24*3600);
- 	assert(0 <= *us && *us < 1000000);
- }
- 
 /* Fiddle years (y), months (m), and days (d) so that
 * 	1 <= *m <= 12
--- 405,408 ----
***************
*** 499,502 ****
--- 473,538 ----
 }
 
+ /* Fiddle out-of-bounds months and days so that the result makes some kind
+ * of sense. The parameters are both inputs and outputs. Returns < 0 on
+ * failure, where failure means the adjusted year is out of bounds.
+ */
+ static int
+ normalize_date(long *year, long *month, long *day)
+ {
+ 	int result;
+ 
+ 	normalize_y_m_d(year, month, day);
+ 	if (MINYEAR <= *year && *year <= MAXYEAR)
+ 		result = 0;
+ 	else {
+ 		PyErr_SetString(PyExc_OverflowError,
+ 				"date value out of range");
+ 		result = -1;
+ 	}
+ 	return result;
+ }
+ 
+ /* 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);
+ }
+ 
+ /* Fiddle days (d), seconds (s), and microseconds (us) so that
+ * 	0 <= *s < 24*3600
+ * 	0 <= *us < 1000000
+ * The input values must be such that the internals don't overflow.
+ * The way this routine is used, we don't get close.
+ */
+ static void
+ normalize_d_s_us(long *d, long *s, long *us)
+ {
+ 	if (*us < 0 || *us >= 1000000) {
+ 		normalize_pair(s, us, 1000000);
+ 		/* |s| can't be bigger than about
+ 		 * |original s| + |original us|/1000000 now.
+ 		 */
+ 
+ 	}
+ 	if (*s < 0 || *s >= 24*3600) {
+ 		normalize_pair(d, s, 24*3600);
+ 		/* |d| can't be bigger than about
+ 		 * |original d| +
+ 		 * (|original s| + |original us|/1000000) / (24*3600) now.
+ 		 */
+ 	}
+ 	assert(0 <= *s && *s < 24*3600);
+ 	assert(0 <= *us && *us < 1000000);
+ }
+ 
 /* Wrap functions from the time module. These aren't directly available
 * from C. Perhaps they should be.
***************
*** 579,582 ****
--- 615,636 ----
 }
 
+ static void
+ set_date_fields(PyDateTime_Date *self, int y, int m, int d)
+ {
+ 	self->hashcode = -1;
+ 	SET_YEAR(self, y);
+ 	SET_MONTH(self, m);
+ 	SET_DAY(self, d);
+ }
+ 
+ static void
+ set_datetime_time_fields(PyDateTime_Date *self, int h, int m, int s, int us)
+ {
+ 	DATE_SET_HOUR(self, h);
+ 	DATE_SET_MINUTE(self, m);
+ 	DATE_SET_SECOND(self, s);
+ 	DATE_SET_MICROSECOND(self, us);
+ }
+ 
 /* Create a date instance with no range checking. */
 static PyObject *
***************
*** 586,595 ****
 
 	self = PyObject_New(PyDateTime_Date, &PyDateTime_DateType);
! 	if (self != NULL) {
! 		self->hashcode = -1;
! 		SET_YEAR(self, year);
! 		SET_MONTH(self, month);
! 		SET_DAY(self, day);
! 	}
 	return (PyObject *) self;
 }
--- 640,645 ----
 
 	self = PyObject_New(PyDateTime_Date, &PyDateTime_DateType);
! 	if (self != NULL)
! 		set_date_fields(self, year, month, day);
 	return (PyObject *) self;
 }
***************
*** 604,615 ****
 	self = PyObject_New(PyDateTime_DateTime, &PyDateTime_DateTimeType);
 	if (self != NULL) {
! 		self->hashcode = -1;
! 		SET_YEAR(self, year);
! 		SET_MONTH(self, month);
! 		SET_DAY(self, day);
! 		DATE_SET_HOUR(self, hour);
! 		DATE_SET_MINUTE(self, minute);
! 		DATE_SET_SECOND(self, second);
! 		DATE_SET_MICROSECOND(self, usecond);
 	}
 	return (PyObject *) self;
--- 654,678 ----
 	self = PyObject_New(PyDateTime_DateTime, &PyDateTime_DateTimeType);
 	if (self != NULL) {
! 		set_date_fields((PyDateTime_Date *)self, year, month, day);
! 		set_datetime_time_fields((PyDateTime_Date *)self,
! 					 hour, minute, second, usecond);
! 	}
! 	return (PyObject *) self;
! }
! 
! /* Create a datetimetz instance with no range checking. */
! static PyObject *
! new_datetimetz(int year, int month, int day, int hour, int minute,
! int second, int usecond, PyObject *tzinfo)
! {
! 	PyDateTime_DateTimeTZ *self;
! 
! 	self = PyObject_New(PyDateTime_DateTimeTZ, &PyDateTime_DateTimeTZType);
! 	if (self != NULL) {
! 		set_date_fields((PyDateTime_Date *)self, year, month, day);
! 		set_datetime_time_fields((PyDateTime_Date *)self,
! 					 hour, minute, second, usecond);
! 		Py_INCREF(tzinfo);
! 		self->tzinfo = tzinfo;
 	}
 	return (PyObject *) self;
***************
*** 791,797 ****
 static PyObject *date_unpickler_object = NULL;
 static PyObject *datetime_unpickler_object = NULL;
 static PyObject *time_unpickler_object = NULL;
 static PyObject *timetz_unpickler_object = NULL;
- static PyObject *tzinfo_unpickler_object = NULL;
 
 #include "obj_delta.c"
--- 854,861 ----
 static PyObject *date_unpickler_object = NULL;
 static PyObject *datetime_unpickler_object = NULL;
+ static PyObject *datetimetz_unpickler_object = NULL;
+ static PyObject *tzinfo_unpickler_object = NULL;
 static PyObject *time_unpickler_object = NULL;
 static PyObject *timetz_unpickler_object = NULL;
 
 #include "obj_delta.c"
***************
*** 801,804 ****
--- 865,869 ----
 #include "obj_tzinfo.c"
 #include "obj_timetz.c"
+ #include "obj_datetimetz.c"
 
 
***************
*** 811,814 ****
--- 876,881 ----
 	{"_datetime_pickler",	(PyCFunction)datetime_pickler,	METH_O, NULL},
 	{"_datetime_unpickler",	(PyCFunction)datetime_unpickler,METH_O, NULL},
+ 	{"_datetimetz_pickler",	(PyCFunction)datetimetz_pickler,METH_O, NULL},
+ 	{"_datetimetz_unpickler",(PyCFunction)datetimetz_unpickler,METH_O, NULL},
 	{"_time_pickler",	(PyCFunction)time_pickler,	METH_O, NULL},
 	{"_time_unpickler",	(PyCFunction)time_unpickler,	METH_O, NULL},
***************
*** 850,853 ****
--- 917,922 ----
 	if (PyType_Ready(&PyDateTime_TimeTZType) < 0)
 		return;
+ 	if (PyType_Ready(&PyDateTime_DateTimeTZType) < 0)
+ 		return;
 
 	/* Pickling support, via registering functions with copy_reg. */
***************
*** 857,924 ****
 		PyObject *copyreg = PyImport_ImportModule("copy_reg");
 
! 		assert(copyreg);
 
 		pickler = PyObject_GetAttrString(m, "_date_pickler");
! 		assert(pickler);
 		date_unpickler_object = PyObject_GetAttrString(m,
 						"_date_unpickler");
! 		assert(date_unpickler_object);
 	 	temp = PyObject_CallMethod(copyreg, "pickle", "OOO",
 	 				 &PyDateTime_DateType,
 	 				 pickler,
 		 date_unpickler_object);
! 		assert(temp);
 		Py_DECREF(temp);
 		Py_DECREF(pickler);
 
 		pickler = PyObject_GetAttrString(m, "_datetime_pickler");
! 		assert(pickler);
 		datetime_unpickler_object = PyObject_GetAttrString(m,
 						"_datetime_unpickler");
! 		assert(datetime_unpickler_object);
 	 	temp = PyObject_CallMethod(copyreg, "pickle", "OOO",
 	 				 &PyDateTime_DateTimeType,
 	 				 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);
 		Py_DECREF(pickler);
 
 		pickler = PyObject_GetAttrString(m, "_timetz_pickler");
! 		assert(pickler);
 		timetz_unpickler_object = PyObject_GetAttrString(m,
 						"_timetz_unpickler");
! 		assert(timetz_unpickler_object);
 	 	temp = PyObject_CallMethod(copyreg, "pickle", "OOO",
 	 				 &PyDateTime_TimeTZType,
 	 				 pickler,
 		 timetz_unpickler_object);
! 		assert(temp);
 		Py_DECREF(temp);
 		Py_DECREF(pickler);
 
 		pickler = PyObject_GetAttrString(m, "_tzinfo_pickler");
! 		assert(pickler);
 		tzinfo_unpickler_object = PyObject_GetAttrString(m,
 							"_tzinfo_unpickler");
! 		assert(tzinfo_unpickler_object);
 	 	temp = PyObject_CallMethod(copyreg, "pickle", "OOO",
 	 				 &PyDateTime_TZInfoType,
 	 				 pickler,
 		 tzinfo_unpickler_object);
! 		assert(temp);
 		Py_DECREF(temp);
 		Py_DECREF(pickler);
--- 926,1006 ----
 		PyObject *copyreg = PyImport_ImportModule("copy_reg");
 
! 		if (copyreg == NULL) return;
 
 		pickler = PyObject_GetAttrString(m, "_date_pickler");
! 		if (pickler == NULL) return;
 		date_unpickler_object = PyObject_GetAttrString(m,
 						"_date_unpickler");
! 		if (date_unpickler_object == NULL) return;
 	 	temp = PyObject_CallMethod(copyreg, "pickle", "OOO",
 	 				 &PyDateTime_DateType,
 	 				 pickler,
 		 date_unpickler_object);
! 		if (temp == NULL) return;
 		Py_DECREF(temp);
 		Py_DECREF(pickler);
 
 		pickler = PyObject_GetAttrString(m, "_datetime_pickler");
! 		if (pickler == NULL) return;
 		datetime_unpickler_object = PyObject_GetAttrString(m,
 						"_datetime_unpickler");
! 		if (datetime_unpickler_object == NULL) return;
 	 	temp = PyObject_CallMethod(copyreg, "pickle", "OOO",
 	 				 &PyDateTime_DateTimeType,
 	 				 pickler,
 		 datetime_unpickler_object);
! 		if (temp == NULL) return;
 		Py_DECREF(temp);
 		Py_DECREF(pickler);
 
 		pickler = PyObject_GetAttrString(m, "_time_pickler");
! 		if (pickler == NULL) return;
 		time_unpickler_object = PyObject_GetAttrString(m,
 						"_time_unpickler");
! 		if (time_unpickler_object == NULL) return;
 	 	temp = PyObject_CallMethod(copyreg, "pickle", "OOO",
 	 				 &PyDateTime_TimeType,
 	 				 pickler,
 		 time_unpickler_object);
! 		if (temp == NULL) return;
 		Py_DECREF(temp);
 		Py_DECREF(pickler);
 
 		pickler = PyObject_GetAttrString(m, "_timetz_pickler");
! 		if (pickler == NULL) return;
 		timetz_unpickler_object = PyObject_GetAttrString(m,
 						"_timetz_unpickler");
! 		if (timetz_unpickler_object == NULL) return;
 	 	temp = PyObject_CallMethod(copyreg, "pickle", "OOO",
 	 				 &PyDateTime_TimeTZType,
 	 				 pickler,
 		 timetz_unpickler_object);
! 		if (temp == NULL) return;
 		Py_DECREF(temp);
 		Py_DECREF(pickler);
 
 		pickler = PyObject_GetAttrString(m, "_tzinfo_pickler");
! 		if (pickler == NULL) return;
 		tzinfo_unpickler_object = PyObject_GetAttrString(m,
 							"_tzinfo_unpickler");
! 		if (tzinfo_unpickler_object == NULL) return;
 	 	temp = PyObject_CallMethod(copyreg, "pickle", "OOO",
 	 				 &PyDateTime_TZInfoType,
 	 				 pickler,
 		 tzinfo_unpickler_object);
! 		if (temp == NULL) return;
! 		Py_DECREF(temp);
! 		Py_DECREF(pickler);
! 
! 		pickler = PyObject_GetAttrString(m, "_datetimetz_pickler");
! 		if (pickler == NULL) return;
! 		datetimetz_unpickler_object = PyObject_GetAttrString(m,
! 						 "_datetimetz_unpickler");
! 		if (datetimetz_unpickler_object == NULL) return;
! 	 	temp = PyObject_CallMethod(copyreg, "pickle", "OOO",
! 	 				 &PyDateTime_DateTimeTZType,
! 	 				 pickler,
! 		 datetimetz_unpickler_object);
! 		if (temp == NULL) return;
 		Py_DECREF(temp);
 		Py_DECREF(pickler);
***************
*** 1011,1014 ****
--- 1093,1114 ----
 
 	x = new_timetz(23, 59, 59, 999999, Py_None);
+ 	if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
+ 		return;
+ 	Py_DECREF(x);
+ 
+ 	x = new_delta(0, 0, 1, 0);
+ 	if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
+ 		return;
+ 	Py_DECREF(x);
+ 
+ 	/* datetimetz values */
+ 	d = PyDateTime_DateTimeTZType.tp_dict;
+ 
+ 	x = new_datetimetz(1, 1, 1, 0, 0, 0, 0, Py_None);
+ 	if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
+ 		return;
+ 	Py_DECREF(x);
+ 
+ 	x = new_datetimetz(MAXYEAR, 12, 31, 23, 59, 59, 999999, Py_None);
 	if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
 		return;
Index: datetime.h
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/datetime.h,v
retrieving revision 1.15
retrieving revision 1.16
diff -C2 -d -r1.15 -r1.16
*** datetime.h	11 Dec 2002 18:54:10 -0000	1.15
--- datetime.h	13 Dec 2002 01:13:46 -0000	1.16
***************
*** 16,21 ****
 * 6 		second 1 byte, 0-59
 * 7 		usecond 3 bytes, 0-999999
! * 10 		tzoffset 2 bytes, signed, in minutes, -1439 .. 1439
! * 12
 */
 
--- 16,20 ----
 * 6 		second 1 byte, 0-59
 * 7 		usecond 3 bytes, 0-999999
! * 10
 */
 
***************
*** 47,50 ****
--- 46,57 ----
 	PyObject_HEAD
 	long hashcode;
+ 	unsigned char data[_PyDateTime_DATETIME_DATASIZE];
+ 	PyObject *tzinfo;
+ } PyDateTime_DateTimeTZ;
+ 
+ typedef struct
+ {
+ 	PyObject_HEAD
+ 	long hashcode;
 	unsigned char data[_PyDateTime_TIME_DATASIZE];
 } PyDateTime_Time;
***************
*** 72,76 ****
 } PyDateTime_TZInfo;
 
! /* Apply for date instances. */
 #define PyDateTime_GET_YEAR(o) ((((PyDateTime_Date*)o)->data[0] << 8) | \
 ((PyDateTime_Date*)o)->data[1])
--- 79,83 ----
 } PyDateTime_TZInfo;
 
! /* Apply for date, datetime, and datetimetz instances. */
 #define PyDateTime_GET_YEAR(o) ((((PyDateTime_Date*)o)->data[0] << 8) | \
 ((PyDateTime_Date*)o)->data[1])
***************
*** 78,82 ****
 #define PyDateTime_GET_DAY(o) (((PyDateTime_Date*)o)->data[3])
 
- /* Apply for datetime and date instances. */
 #define PyDateTime_DATE_GET_HOUR(o) (((PyDateTime_DateTime*)o)->data[4])
 #define PyDateTime_DATE_GET_MINUTE(o) (((PyDateTime_DateTime*)o)->data[5])
--- 85,88 ----
Index: obj_date.c
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/obj_date.c,v
retrieving revision 1.48
retrieving revision 1.49
diff -C2 -d -r1.48 -r1.49
*** obj_date.c	12 Dec 2002 18:48:01 -0000	1.48
--- obj_date.c	13 Dec 2002 01:13:46 -0000	1.49
***************
*** 149,173 ****
 }
 
! /* date arithmetic. */
! 
! /* Fiddle out-of-bounds months and days so that the result makes some kind
! * of sense. The parameters are both inputs and outputs. Returns < 0 on
! * failure, where failure means the adjusted year is out of bounds.
 */
- static int
- normalize_date(long *year, long *month, long *day)
- {
- 	int result;
- 
- 	normalize_y_m_d(year, month, day);
- 	if (MINYEAR <= *year && *year <= MAXYEAR)
- 		result = 0;
- 	else {
- 		PyErr_SetString(PyExc_OverflowError,
- 				"date value out of range");
- 		result = -1;
- 	}
- 	return result;
- }
 
 /* date + timedelta -> date. If arg negate is true, subtract the timedelta
--- 149,155 ----
 }
 
! /*
! * Date arithmetic.
 */
 
 /* date + timedelta -> date. If arg negate is true, subtract the timedelta
Index: obj_datetime.c
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/datetime/obj_datetime.c,v
retrieving revision 1.46
retrieving revision 1.47
diff -C2 -d -r1.46 -r1.47
*** obj_datetime.c	12 Dec 2002 18:48:01 -0000	1.46
--- obj_datetime.c	13 Dec 2002 01:13:46 -0000	1.47
***************
*** 253,271 ****
 /* 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)
--- 253,256 ----

AltStyle によって変換されたページ (->オリジナル) /