1 /* adapter_datetime.c - python date/time objects
3 * Copyright (C) 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>
30 #define PSYCOPG_MODULE
31 #include "psycopg/config.h"
32 #include "psycopg/python.h"
33 #include "psycopg/psycopg.h"
34 #include "psycopg/adapter_datetime.h"
35 #include "psycopg/microprotocols_proto.h"
38 /* the pointer to the datetime module API is initialized by the module init
39 code, we just need to grab it */
40 extern PyObject* pyDateTimeModuleP;
41 extern PyObject *pyDateTypeP;
42 extern PyObject *pyTimeTypeP;
43 extern PyObject *pyDateTimeTypeP;
44 extern PyObject *pyDeltaTypeP;
46 extern PyObject *pyPsycopgTzModule;
47 extern PyObject *pyPsycopgTzLOCAL;
49 /* datetime_str, datetime_getquoted - return result of quoting */
52 pydatetime_str(pydatetimeObject *self)
54 if (self->type <= PSYCO_DATETIME_TIMESTAMP) {
56 PyObject *iso = PyObject_CallMethod(self->wrapped, "isoformat", NULL);
58 res = PyString_FromFormat("'%s'", PyString_AsString(iso));
64 PyDateTime_Delta *obj = (PyDateTime_Delta*)self->wrapped;
68 int a = obj->microseconds;
70 for (i=0; i < 6 ; i++) {
71 buffer[5-i] = '0' + (a % 10);
76 return PyString_FromFormat("'%d days %d.%s seconds'",
77 obj->days, obj->seconds, buffer);
82 pydatetime_getquoted(pydatetimeObject *self, PyObject *args)
84 if (!PyArg_ParseTuple(args, "")) return NULL;
85 return pydatetime_str(self);
89 pydatetime_conform(pydatetimeObject *self, PyObject *args)
91 PyObject *res, *proto;
93 if (!PyArg_ParseTuple(args, "O", &proto)) return NULL;
95 if (proto == (PyObject*)&isqlquoteType)
96 res = (PyObject*)self;
104 /** the DateTime wrapper object **/
106 /* object member list */
108 static struct PyMemberDef pydatetimeObject_members[] = {
109 {"adapted", T_OBJECT, offsetof(pydatetimeObject, wrapped), RO},
110 {"type", T_INT, offsetof(pydatetimeObject, type), RO},
114 /* object method table */
116 static PyMethodDef pydatetimeObject_methods[] = {
117 {"getquoted", (PyCFunction)pydatetime_getquoted, METH_VARARGS,
118 "getquoted() -> wrapped object value as SQL date/time"},
119 {"__conform__", (PyCFunction)pydatetime_conform, METH_VARARGS, NULL},
120 {NULL} /* Sentinel */
123 /* initialization and finalization methods */
126 pydatetime_setup(pydatetimeObject *self, PyObject *obj, int type)
128 Dprintf("pydatetime_setup: init datetime object at %p, refcnt = %d",
129 self, ((PyObject *)self)->ob_refcnt);
133 Py_INCREF(self->wrapped);
135 Dprintf("pydatetime_setup: good pydatetime object at %p, refcnt = %d",
136 self, ((PyObject *)self)->ob_refcnt);
141 pydatetime_dealloc(PyObject* obj)
143 pydatetimeObject *self = (pydatetimeObject *)obj;
145 Py_XDECREF(self->wrapped);
147 Dprintf("mpydatetime_dealloc: deleted pydatetime object at %p, "
148 "refcnt = %d", obj, obj->ob_refcnt);
150 obj->ob_type->tp_free(obj);
154 pydatetime_init(PyObject *obj, PyObject *args, PyObject *kwds)
157 int type = -1; /* raise an error if type was not passed! */
159 if (!PyArg_ParseTuple(args, "O|i", &dt, &type))
162 return pydatetime_setup((pydatetimeObject *)obj, dt, type);
166 pydatetime_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
168 return type->tp_alloc(type, 0);
172 pydatetime_del(PyObject* self)
178 pydatetime_repr(pydatetimeObject *self)
180 return PyString_FromFormat("<psycopg2._psycopg.datetime object at %p>",
186 #define pydatetimeType_doc \
187 "datetime(datetime, type) -> new datetime wrapper object"
189 PyTypeObject pydatetimeType = {
190 PyObject_HEAD_INIT(NULL)
192 "psycopg2._psycopg.datetime",
193 sizeof(pydatetimeObject),
195 pydatetime_dealloc, /*tp_dealloc*/
201 (reprfunc)pydatetime_repr, /*tp_repr*/
203 0, /*tp_as_sequence*/
208 (reprfunc)pydatetime_str, /*tp_str*/
213 Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/
215 pydatetimeType_doc, /*tp_doc*/
220 0, /*tp_richcompare*/
221 0, /*tp_weaklistoffset*/
226 /* Attribute descriptor and subclassing stuff */
228 pydatetimeObject_methods, /*tp_methods*/
229 pydatetimeObject_members, /*tp_members*/
238 pydatetime_init, /*tp_init*/
239 0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/
240 pydatetime_new, /*tp_new*/
241 (freefunc)pydatetime_del, /*tp_free Low-level free-memory routine */
242 0, /*tp_is_gc For PyObject_IS_GC */
244 0, /*tp_mro method resolution order */
251 /** module-level functions **/
253 #ifdef PSYCOPG_DEFAULT_PYDATETIME
256 psyco_Date(PyObject *self, PyObject *args)
258 PyObject *res = NULL;
259 int year, month, day;
261 PyObject* obj = NULL;
263 if (!PyArg_ParseTuple(args, "iii", &year, &month, &day))
266 obj = PyObject_CallFunction(pyDateTypeP, "iii", year, month, day);
269 res = PyObject_CallFunction((PyObject *)&pydatetimeType,
270 "Oi", obj, PSYCO_DATETIME_DATE);
278 psyco_Time(PyObject *self, PyObject *args)
280 PyObject *res = NULL;
281 PyObject *tzinfo = NULL;
282 int hours, minutes=0;
283 double micro, seconds=0.0;
285 PyObject* obj = NULL;
287 if (!PyArg_ParseTuple(args, "iid|O", &hours, &minutes, &seconds,
291 micro = (seconds - floor(seconds)) * 1000000.0;
294 obj = PyObject_CallFunction(pyTimeTypeP, "iiii",
295 hours, minutes, (int)round(seconds), (int)round(micro));
297 obj = PyObject_CallFunction(pyTimeTypeP, "iiiiO",
298 hours, minutes, (int)round(seconds), (int)round(micro), tzinfo);
301 res = PyObject_CallFunction((PyObject *)&pydatetimeType,
302 "Oi", obj, PSYCO_DATETIME_TIME);
310 psyco_Timestamp(PyObject *self, PyObject *args)
312 PyObject *res = NULL;
313 PyObject *tzinfo = NULL;
314 int year, month, day;
315 int hour=0, minute=0; /* default to midnight */
316 double micro, second=0.0;
318 PyObject* obj = NULL;
320 if (!PyArg_ParseTuple(args, "lii|iidO", &year, &month, &day,
321 &hour, &minute, &second, &tzinfo))
324 micro = (second - floor(second)) * 1000000.0;
327 obj = PyObject_CallFunction(pyDateTimeTypeP, "iiiiiii",
328 year, month, day, hour, minute, (int)round(second),
331 obj = PyObject_CallFunction(pyDateTimeTypeP, "iiiiiiiO",
332 year, month, day, hour, minute, (int)round(second),
333 (int)round(micro), tzinfo);
336 res = PyObject_CallFunction((PyObject *)&pydatetimeType,
337 "Oi", obj, PSYCO_DATETIME_TIMESTAMP);
345 psyco_DateFromTicks(PyObject *self, PyObject *args)
347 PyObject *res = NULL;
352 if (!PyArg_ParseTuple(args, "d", &ticks))
355 t = (time_t)round(ticks);
356 if (localtime_r(&t, &tm)) {
357 args = Py_BuildValue("iii", tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday);
359 res = psyco_Date(self, args);
367 psyco_TimeFromTicks(PyObject *self, PyObject *args)
369 PyObject *res = NULL;
374 if (!PyArg_ParseTuple(args,"d", &ticks))
377 t = (time_t)round(ticks);
378 if (localtime_r(&t, &tm)) {
379 args = Py_BuildValue("iid", tm.tm_hour, tm.tm_min, (double)tm.tm_sec);
381 res = psyco_Time(self, args);
389 psyco_TimestampFromTicks(PyObject *self, PyObject *args)
391 PyObject *res = NULL;
396 if (!PyArg_ParseTuple(args,"d", &ticks))
399 t = (time_t)round(ticks);
400 if (localtime_r(&t, &tm)) {
401 args = Py_BuildValue("iiiiidO",
402 tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday,
403 tm.tm_hour, tm.tm_min, (double)tm.tm_sec,
406 res = psyco_Timestamp(self, args);
416 psyco_DateFromPy(PyObject *self, PyObject *args)
420 if (!PyArg_ParseTuple(args, "O!", pyDateTypeP, &obj))
423 return PyObject_CallFunction((PyObject *)&pydatetimeType, "Oi", obj,
424 PSYCO_DATETIME_DATE);
428 psyco_TimeFromPy(PyObject *self, PyObject *args)
432 if (!PyArg_ParseTuple(args, "O!", pyTimeTypeP, &obj))
435 return PyObject_CallFunction((PyObject *)&pydatetimeType, "Oi", obj,
436 PSYCO_DATETIME_TIME);
440 psyco_TimestampFromPy(PyObject *self, PyObject *args)
444 if (!PyArg_ParseTuple(args, "O!", pyDateTimeTypeP, &obj))
447 return PyObject_CallFunction((PyObject *)&pydatetimeType, "Oi", obj,
448 PSYCO_DATETIME_TIMESTAMP);
452 psyco_IntervalFromPy(PyObject *self, PyObject *args)
456 if (!PyArg_ParseTuple(args, "O!", pyDeltaTypeP, &obj))
459 return PyObject_CallFunction((PyObject *)&pydatetimeType, "Oi", obj,
460 PSYCO_DATETIME_INTERVAL);