1 /* typecast_datetime.c - date and time typecasting functions to python types
3 * Copyright (C) 2001-2003 Federico Di Gregorio <fog@debian.org>
5 * This file is part of the psycopg module.
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.
26 /* the pointer to the datetime module API is initialized by the module init
27 code, we just need to grab it */
28 extern PyObject* pyDateTimeModuleP;
29 extern PyObject *pyDateTypeP;
30 extern PyObject *pyTimeTypeP;
31 extern PyObject *pyDateTimeTypeP;
32 extern PyObject *pyDeltaTypeP;
34 /** DATE - cast a date into a date python object **/
37 typecast_PYDATE_cast(char *str, int len, PyObject *curs)
42 if (str == NULL) {Py_INCREF(Py_None); return Py_None;}
44 if (!strcmp(str, "infinity") || !strcmp(str, "-infinity")) {
46 obj = PyObject_GetAttrString(pyDateTypeP, "min");
49 obj = PyObject_GetAttrString(pyDateTypeP, "max");
54 n = typecast_parse_date(str, NULL, &len, &y, &m, &d);
55 Dprintf("typecast_PYDATE_cast: "
56 "n = %d, len = %d, y = %d, m = %d, d = %d",
59 PyErr_SetString(DataError, "unable to parse date");
62 obj = PyObject_CallFunction(pyDateTypeP, "iii", y, m, d);
68 /** DATETIME - cast a timestamp into a datetime python object **/
71 typecast_PYDATETIME_cast(char *str, int len, PyObject *curs)
75 int hh=0, mm=0, ss=0, us=0, tz=0;
78 if (str == NULL) {Py_INCREF(Py_None); return Py_None;}
80 /* check for infinity */
81 if (!strcmp(str, "infinity") || !strcmp(str, "-infinity")) {
83 obj = PyObject_GetAttrString(pyDateTimeTypeP, "min");
86 obj = PyObject_GetAttrString(pyDateTimeTypeP, "max");
91 Dprintf("typecast_PYDATETIME_cast: s = %s", str);
92 n = typecast_parse_date(str, &tp, &len, &y, &m, &d);
93 Dprintf("typecast_PYDATE_cast: tp = %p "
94 "n = %d, len = %d, y = %d, m = %d, d = %d",
97 PyErr_SetString(DataError, "unable to parse date");
101 n = typecast_parse_time(tp, NULL, &len, &hh, &mm, &ss, &us, &tz);
102 Dprintf("typecast_PYDATETIME_cast: n = %d, len = %d, "
103 "hh = %d, mm = %d, ss = %d, us = %d, tz = %d",
104 n, len, hh, mm, ss, us, tz);
105 if (n < 3 || n > 5) {
106 PyErr_SetString(DataError, "unable to parse time");
115 if (n == 5 && ((cursorObject*)curs)->tzinfo_factory != Py_None) {
116 /* we have a time zone, calculate minutes and create
117 appropriate tzinfo object calling the factory */
119 Dprintf("typecast_PYDATETIME_cast: UTC offset = %dm", tz);
120 tzinfo = PyObject_CallFunction(
121 ((cursorObject*)curs)->tzinfo_factory, "i", tz);
122 obj = PyObject_CallFunction(pyDateTimeTypeP, "iiiiiiiO",
123 y, m, d, hh, mm, ss, us, tzinfo);
124 Dprintf("typecast_PYDATETIME_cast: tzinfo: %p, refcnt = %d",
125 tzinfo, tzinfo->ob_refcnt);
129 obj = PyObject_CallFunction(pyDateTimeTypeP, "iiiiiii",
130 y, m, d, hh, mm, ss, us);
136 /** TIME - parse time into a time object **/
139 typecast_PYTIME_cast(char *str, int len, PyObject *curs)
141 PyObject* obj = NULL;
142 int n, hh=0, mm=0, ss=0, us=0, tz=0;
144 if (str == NULL) {Py_INCREF(Py_None); return Py_None;}
146 n = typecast_parse_time(str, NULL, &len, &hh, &mm, &ss, &us, &tz);
147 Dprintf("typecast_PYTIME_cast: n = %d, len = %d, "
148 "hh = %d, mm = %d, ss = %d, us = %d, tz = %d",
149 n, len, hh, mm, ss, us, tz);
151 if (n < 3 || n > 5) {
152 PyErr_SetString(DataError, "unable to parse time");
159 obj = PyObject_CallFunction(pyTimeTypeP, "iiii", hh, mm, ss, us);
164 /** INTERVAL - parse an interval into a timedelta object **/
167 typecast_PYINTERVAL_cast(char *str, int len, PyObject *curs)
169 long years = 0, months = 0, days = 0;
170 double hours = 0.0, minutes = 0.0, seconds = 0.0, hundredths = 0.0;
171 double v = 0.0, sign = 1.0, denominator = 1.0;
175 if (str == NULL) {Py_INCREF(Py_None); return Py_None;}
177 Dprintf("typecast_PYINTERVAL_cast: s = %s", str);
179 while (len-- > 0 && *str) {
186 case '0': case '1': case '2': case '3': case '4':
187 case '5': case '6': case '7': case '8': case '9':
188 v = v*10 + (double)*str - (double)'0';
196 years = (long)(v*sign);
197 str = skip_until_space2(str, &len);
198 v = 0.0; sign = 1.0; part = 1;
204 months = (long)(v*sign);
205 str = skip_until_space2(str, &len);
206 v = 0.0; sign = 1.0; part = 2;
212 days = (long)(v*sign);
213 str = skip_until_space2(str, &len);
214 v = 0.0; sign = 1.0; part = 3;
223 else if (part == 4) {
243 /* manage last value, be it minutes or seconds or hundredths of a second */
247 else if (part == 5) {
250 else if (part == 6) {
252 hundredths = hundredths/denominator;
255 /* calculates seconds */
257 seconds = - (hundredths + seconds + minutes*60 + hours*3600);
260 seconds += hundredths + minutes*60 + hours*3600;
263 /* calculates days */
264 days += years*365 + months*30;
266 micro = (seconds - floor(seconds)) * 1000000.0;
267 sec = (int)floor(seconds);
268 return PyObject_CallFunction(pyDeltaTypeP, "iii",
269 days, sec, (int)round(micro));
272 /* psycopg defaults to using python datetime types */
274 #ifdef PSYCOPG_DEFAULT_PYDATETIME
275 #define typecast_DATE_cast typecast_PYDATE_cast
276 #define typecast_TIME_cast typecast_PYTIME_cast
277 #define typecast_INTERVAL_cast typecast_PYINTERVAL_cast
278 #define typecast_DATETIME_cast typecast_PYDATETIME_cast