~ubuntu-branches/ubuntu/hardy/psycopg2/hardy

« back to all changes in this revision

Viewing changes to psycopg/typecast_datetime.c

  • Committer: Bazaar Package Importer
  • Author(s): Fabio Tranchitella
  • Date: 2006-08-09 10:28:30 UTC
  • Revision ID: james.westby@ubuntu.com-20060809102830-grac1dsp24uyqfp4
Tags: upstream-2.0.4
ImportĀ upstreamĀ versionĀ 2.0.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* typecast_datetime.c - date and time typecasting functions to python types
 
2
 *
 
3
 * Copyright (C) 2001-2003 Federico Di Gregorio <fog@debian.org>
 
4
 *
 
5
 * This file is part of the psycopg module.
 
6
 *
 
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.
 
11
 *
 
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.
 
16
 *
 
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.
 
20
 */
 
21
 
 
22
#include <math.h>
 
23
#include "datetime.h"
 
24
 
 
25
 
 
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;
 
33
 
 
34
/** DATE - cast a date into a date python object **/
 
35
 
 
36
static PyObject *
 
37
typecast_PYDATE_cast(char *str, int len, PyObject *curs)
 
38
{
 
39
    PyObject* obj = NULL;
 
40
    int n, y=0, m=0, d=0;
 
41
     
 
42
    if (str == NULL) {Py_INCREF(Py_None); return Py_None;}
 
43
    
 
44
    if (!strcmp(str, "infinity") || !strcmp(str, "-infinity")) {
 
45
        if (str[0] == '-') {
 
46
            obj = PyObject_GetAttrString(pyDateTypeP, "min");
 
47
        }
 
48
        else {
 
49
            obj = PyObject_GetAttrString(pyDateTypeP, "max");
 
50
        }
 
51
    }
 
52
 
 
53
    else {
 
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",
 
57
                 n, len, y, m, d);
 
58
        if (n != 3) {
 
59
            PyErr_SetString(DataError, "unable to parse date");
 
60
        }
 
61
        else {
 
62
            obj = PyObject_CallFunction(pyDateTypeP, "iii", y, m, d);
 
63
        }
 
64
    }
 
65
    return obj;
 
66
}
 
67
 
 
68
/** DATETIME - cast a timestamp into a datetime python object **/
 
69
 
 
70
static PyObject *
 
71
typecast_PYDATETIME_cast(char *str, int len, PyObject *curs)
 
72
{
 
73
    PyObject* obj = NULL;
 
74
    int n, y=0, m=0, d=0;
 
75
    int hh=0, mm=0, ss=0, us=0, tz=0;
 
76
    char *tp = NULL;
 
77
    
 
78
    if (str == NULL) {Py_INCREF(Py_None); return Py_None;}
 
79
    
 
80
    /* check for infinity */
 
81
    if (!strcmp(str, "infinity") || !strcmp(str, "-infinity")) {
 
82
        if (str[0] == '-') {
 
83
            obj = PyObject_GetAttrString(pyDateTimeTypeP, "min");
 
84
        }
 
85
        else {
 
86
            obj = PyObject_GetAttrString(pyDateTimeTypeP, "max");
 
87
        }
 
88
    }
 
89
 
 
90
    else {
 
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",
 
95
                 tp, n, len, y, m, d);        
 
96
        if (n != 3) {
 
97
            PyErr_SetString(DataError, "unable to parse date");
 
98
        }
 
99
        
 
100
        if (len > 0) {
 
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");
 
107
            }
 
108
        }
 
109
        
 
110
        if (ss > 59) {
 
111
            mm += 1;
 
112
            ss -= 60;
 
113
        }
 
114
        
 
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 */
 
118
            PyObject *tzinfo;
 
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);
 
126
            Py_XDECREF(tzinfo);
 
127
        }
 
128
        else {
 
129
            obj = PyObject_CallFunction(pyDateTimeTypeP, "iiiiiii",
 
130
                 y, m, d, hh, mm, ss, us);
 
131
        }
 
132
    }
 
133
    return obj;
 
134
}
 
135
 
 
136
/** TIME - parse time into a time object **/
 
137
 
 
138
static PyObject *
 
139
typecast_PYTIME_cast(char *str, int len, PyObject *curs)
 
140
{
 
141
    PyObject* obj = NULL;
 
142
    int n, hh=0, mm=0, ss=0, us=0, tz=0;
 
143
    
 
144
    if (str == NULL) {Py_INCREF(Py_None); return Py_None;}
 
145
        
 
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);
 
150
                
 
151
    if (n < 3 || n > 5) {
 
152
        PyErr_SetString(DataError, "unable to parse time");
 
153
    }
 
154
    else {
 
155
        if (ss > 59) {
 
156
            mm += 1;
 
157
            ss -= 60;
 
158
        }
 
159
        obj = PyObject_CallFunction(pyTimeTypeP, "iiii", hh, mm, ss, us);
 
160
    }
 
161
    return obj;          
 
162
}
 
163
 
 
164
/** INTERVAL - parse an interval into a timedelta object **/
 
165
 
 
166
static PyObject *
 
167
typecast_PYINTERVAL_cast(char *str, int len, PyObject *curs)
 
168
{
 
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;
 
172
    int part = 0, sec;
 
173
    double micro;
 
174
 
 
175
    if (str == NULL) {Py_INCREF(Py_None); return Py_None;}
 
176
 
 
177
    Dprintf("typecast_PYINTERVAL_cast: s = %s", str);
 
178
    
 
179
    while (len-- > 0 && *str) {
 
180
        switch (*str) {
 
181
 
 
182
        case '-':
 
183
            sign = -1.0;
 
184
            break;
 
185
 
 
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';
 
189
            if (part == 6){
 
190
                denominator *= 10;
 
191
            }
 
192
            break;
 
193
 
 
194
        case 'y':
 
195
            if (part == 0) {
 
196
                years = (long)(v*sign);
 
197
                str = skip_until_space2(str, &len);
 
198
                v = 0.0; sign = 1.0; part = 1;
 
199
            }
 
200
            break;
 
201
 
 
202
        case 'm':
 
203
            if (part <= 1) {
 
204
                months = (long)(v*sign);
 
205
                str = skip_until_space2(str, &len);
 
206
                v = 0.0; sign = 1.0; part = 2;
 
207
            }
 
208
            break;
 
209
 
 
210
        case 'd':
 
211
            if (part <= 2) {
 
212
                days = (long)(v*sign);
 
213
                str = skip_until_space2(str, &len);
 
214
                v = 0.0; sign = 1.0; part = 3;
 
215
            }
 
216
            break;
 
217
 
 
218
        case ':':
 
219
            if (part <= 3) {
 
220
                hours = v;
 
221
                v = 0.0; part = 4;
 
222
            }
 
223
            else if (part == 4) {
 
224
                minutes = v;
 
225
                v = 0.0; part = 5;
 
226
            }
 
227
            break;
 
228
 
 
229
        case '.':
 
230
            if (part == 5) {
 
231
                seconds = v;
 
232
                v = 0.0; part = 6;
 
233
            }
 
234
            break;   
 
235
 
 
236
        default:
 
237
            break;
 
238
        }
 
239
        
 
240
        str++;
 
241
    }
 
242
 
 
243
    /* manage last value, be it minutes or seconds or hundredths of a second */
 
244
    if (part == 4) {
 
245
        minutes = v;
 
246
    }
 
247
    else if (part == 5) {
 
248
        seconds = v;
 
249
    }
 
250
    else if (part == 6) {
 
251
        hundredths = v;
 
252
        hundredths = hundredths/denominator;
 
253
    }
 
254
    
 
255
    /* calculates seconds */
 
256
    if (sign < 0.0) {
 
257
        seconds = - (hundredths + seconds + minutes*60 + hours*3600);
 
258
    }
 
259
    else {
 
260
        seconds += hundredths + minutes*60 + hours*3600;
 
261
    }
 
262
 
 
263
    /* calculates days */ 
 
264
    days += years*365 + months*30;
 
265
 
 
266
    micro = (seconds - floor(seconds)) * 1000000.0;
 
267
    sec = (int)floor(seconds);
 
268
    return PyObject_CallFunction(pyDeltaTypeP, "iii",
 
269
                                 days, sec, (int)round(micro));
 
270
}
 
271
 
 
272
/* psycopg defaults to using python datetime types */
 
273
 
 
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
 
279
#endif