1 /* adapter_mxdatetime.c - mx date/time objects
3 * Copyright (C) 2003-2004 Federico Di Gregorio <fog@debian.org>
5 * This file is part of psycopg.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2,
10 * or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include <structmember.h>
24 #include <stringobject.h>
25 #include <mxDateTime.h>
28 #define PSYCOPG_MODULE
29 #include "psycopg/config.h"
30 #include "psycopg/python.h"
31 #include "psycopg/psycopg.h"
32 #include "psycopg/adapter_mxdatetime.h"
33 #include "psycopg/microprotocols_proto.h"
35 /* the pointer to the mxDateTime API is initialized by the module init code,
36 we just need to grab it */
37 extern mxDateTimeModule_APIObject *mxDateTimeP;
40 /* mxdatetime_str, mxdatetime_getquoted - return result of quoting */
43 mxdatetime_str(mxdatetimeObject *self)
45 PyObject *str = NULL, *res = NULL;
49 case PSYCO_MXDATETIME_DATE:
50 case PSYCO_MXDATETIME_TIMESTAMP:
51 str = PyObject_Str(self->wrapped);
53 /* given the limitation of the mx.DateTime module that uses the same
54 type for both date and timestamp values we need to do some black
55 magic and make sure we're not using an adapt()ed timestamp as a
57 if (strncmp(&(PyString_AsString(str)[11]), "00:00:00.000", 12) == 0) {
59 PyString_FromStringAndSize(PyString_AsString(str), 10);
65 case PSYCO_MXDATETIME_TIME:
66 case PSYCO_MXDATETIME_INTERVAL:
67 str = PyObject_Str(self->wrapped);
69 /* given the limitation of the mx.DateTime module that uses the same
70 type for both time and delta values we need to do some black magic
71 and make sure we're not using an adapt()ed interval as a simple
73 if (PyString_Size(str) > 8 && PyString_AsString(str)[8] == ':') {
74 mxDateTimeDeltaObject *obj = (mxDateTimeDeltaObject*)self->wrapped;
79 double ss = obj->hour*3600.0 + obj->minute*60.0 + obj->second;
80 int us = (int)((ss - floor(ss))*1000000);
82 for (i=1000000, j=0; i > 0 ; i /= 10) {
89 res = PyString_FromFormat("'%ld days %d.%s seconds'",
90 obj->day, (int)round(ss), buffer);
95 if (str != NULL && res == NULL) {
96 res = PyString_FromFormat("'%s'", PyString_AsString(str));
104 mxdatetime_getquoted(mxdatetimeObject *self, PyObject *args)
106 if (!PyArg_ParseTuple(args, "")) return NULL;
107 return mxdatetime_str(self);
111 mxdatetime_conform(mxdatetimeObject *self, PyObject *args)
113 PyObject *res, *proto;
115 if (!PyArg_ParseTuple(args, "O", &proto)) return NULL;
117 if (proto == (PyObject*)&isqlquoteType)
118 res = (PyObject*)self;
126 /** the MxDateTime object **/
128 /* object member list */
130 static struct PyMemberDef mxdatetimeObject_members[] = {
131 {"adapted", T_OBJECT, offsetof(mxdatetimeObject, wrapped), RO},
132 {"type", T_INT, offsetof(mxdatetimeObject, type), RO},
136 /* object method table */
138 static PyMethodDef mxdatetimeObject_methods[] = {
139 {"getquoted", (PyCFunction)mxdatetime_getquoted, METH_VARARGS,
140 "getquoted() -> wrapped object value as SQL date/time"},
141 {"__conform__", (PyCFunction)mxdatetime_conform, METH_VARARGS, NULL},
142 {NULL} /* Sentinel */
145 /* initialization and finalization methods */
148 mxdatetime_setup(mxdatetimeObject *self, PyObject *obj, int type)
150 Dprintf("mxdatetime_setup: init mxdatetime object at %p, refcnt = %d",
151 self, ((PyObject *)self)->ob_refcnt);
155 Py_INCREF(self->wrapped);
157 Dprintf("mxdatetime_setup: good mxdatetime object at %p, refcnt = %d",
158 self, ((PyObject *)self)->ob_refcnt);
163 mxdatetime_dealloc(PyObject* obj)
165 mxdatetimeObject *self = (mxdatetimeObject *)obj;
167 Py_XDECREF(self->wrapped);
169 Dprintf("mxdatetime_dealloc: deleted mxdatetime object at %p, refcnt = %d",
170 obj, obj->ob_refcnt);
172 obj->ob_type->tp_free(obj);
176 mxdatetime_init(PyObject *obj, PyObject *args, PyObject *kwds)
179 int type = -1; /* raise an error if type was not passed! */
181 if (!PyArg_ParseTuple(args, "O|i", &mx, &type))
184 return mxdatetime_setup((mxdatetimeObject *)obj, mx, type);
188 mxdatetime_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
190 return type->tp_alloc(type, 0);
194 mxdatetime_del(PyObject* self)
200 mxdatetime_repr(mxdatetimeObject *self)
202 return PyString_FromFormat("<psycopg2._psycopg.MxDateTime object at %p>",
208 #define mxdatetimeType_doc \
209 "MxDateTime(mx, type) -> new mx.DateTime wrapper object"
211 PyTypeObject mxdatetimeType = {
212 PyObject_HEAD_INIT(NULL)
214 "psycopg2._psycopg.MxDateTime",
215 sizeof(mxdatetimeObject),
217 mxdatetime_dealloc, /*tp_dealloc*/
223 (reprfunc)mxdatetime_repr, /*tp_repr*/
225 0, /*tp_as_sequence*/
230 (reprfunc)mxdatetime_str, /*tp_str*/
235 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
237 mxdatetimeType_doc, /*tp_doc*/
242 0, /*tp_richcompare*/
243 0, /*tp_weaklistoffset*/
248 /* Attribute descriptor and subclassing stuff */
250 mxdatetimeObject_methods, /*tp_methods*/
251 mxdatetimeObject_members, /*tp_members*/
260 mxdatetime_init, /*tp_init*/
261 PyType_GenericAlloc, /*tp_alloc*/
262 mxdatetime_new, /*tp_new*/
263 (freefunc)mxdatetime_del, /*tp_free Low-level free-memory routine */
264 0, /*tp_is_gc For PyObject_IS_GC */
266 0, /*tp_mro method resolution order */
273 /** module-level functions **/
275 #ifdef PSYCOPG_DEFAULT_MXDATETIME
278 psyco_Date(PyObject *self, PyObject *args)
281 int year, month, day;
283 if (!PyArg_ParseTuple(args, "iii", &year, &month, &day))
286 mx = mxDateTimeP->DateTime_FromDateAndTime(year, month, day, 0, 0, 0.0);
287 if (mx == NULL) return NULL;
289 res = PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx,
290 PSYCO_MXDATETIME_DATE);
296 psyco_Time(PyObject *self, PyObject *args)
299 int hours, minutes=0;
302 if (!PyArg_ParseTuple(args, "iid", &hours, &minutes, &seconds))
305 mx = mxDateTimeP->DateTimeDelta_FromTime(hours, minutes, seconds);
306 if (mx == NULL) return NULL;
308 res = PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx,
309 PSYCO_MXDATETIME_TIME);
315 psyco_Timestamp(PyObject *self, PyObject *args)
318 int year, month, day;
319 int hour=0, minute=0; /* default to midnight */
322 if (!PyArg_ParseTuple(args, "lii|iid", &year, &month, &day,
323 &hour, &minute, &second))
326 mx = mxDateTimeP->DateTime_FromDateAndTime(year, month, day,
327 hour, minute, second);
328 if (mx == NULL) return NULL;
330 res = PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx,
331 PSYCO_MXDATETIME_TIMESTAMP);
337 psyco_DateFromTicks(PyObject *self, PyObject *args)
342 if (!PyArg_ParseTuple(args,"d", &ticks))
345 if (!(mx = mxDateTimeP->DateTime_FromTicks(ticks)))
348 res = PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx,
349 PSYCO_MXDATETIME_DATE);
355 psyco_TimeFromTicks(PyObject *self, PyObject *args)
357 PyObject *res, *mx, *dt;
360 if (!PyArg_ParseTuple(args,"d", &ticks))
363 if (!(dt = mxDateTimeP->DateTime_FromTicks(ticks)))
366 if (!(mx = mxDateTimeP->DateTimeDelta_FromDaysAndSeconds(
367 0, ((mxDateTimeObject*)dt)->abstime)))
374 res = PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx,
375 PSYCO_MXDATETIME_TIME);
381 psyco_TimestampFromTicks(PyObject *self, PyObject *args)
386 if (!PyArg_ParseTuple(args, "d", &ticks))
389 if (!(mx = mxDateTimeP->DateTime_FromTicks(ticks)))
392 res = PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx,
393 PSYCO_MXDATETIME_TIMESTAMP);
401 psyco_DateFromMx(PyObject *self, PyObject *args)
405 if (!PyArg_ParseTuple(args, "O!", mxDateTimeP->DateTime_Type, &mx))
408 return PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx,
409 PSYCO_MXDATETIME_DATE);
413 psyco_TimeFromMx(PyObject *self, PyObject *args)
417 if (!PyArg_ParseTuple(args, "O!", mxDateTimeP->DateTimeDelta_Type, &mx))
420 return PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx,
421 PSYCO_MXDATETIME_TIME);
425 psyco_TimestampFromMx(PyObject *self, PyObject *args)
429 if (!PyArg_ParseTuple(args, "O!", mxDateTimeP->DateTime_Type, &mx))
432 return PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx,
433 PSYCO_MXDATETIME_TIMESTAMP);
437 psyco_IntervalFromMx(PyObject *self, PyObject *args)
441 if (!PyArg_ParseTuple(args, "O!", mxDateTimeP->DateTime_Type, &mx))
444 return PyObject_CallFunction((PyObject *)&mxdatetimeType, "Oi", mx,
445 PSYCO_MXDATETIME_INTERVAL);