Merge remote-tracking branch 'origin/pycurl' into planetlab-4_0-branch
[plcapi.git] / trunk / psycopg2 / psycopg / typecast_mxdatetime.c
1 /* typecast_mxdatetime.c - date and time typecasting functions to mx 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 "mxDateTime.h"
23
24 /* the pointer to the mxDateTime API is initialized by the module init code,
25    we just need to grab it */
26 extern mxDateTimeModule_APIObject *mxDateTimeP;
27
28 /** DATE - cast a date into mx.DateTime python object **/
29
30 static PyObject *
31 typecast_MXDATE_cast(char *str, int len, PyObject *curs)
32 {
33     int n, y=0, m=0, d=0;
34     int hh=0, mm=0, ss=0, us=0, tz=0;
35     char *tp = NULL;
36     
37     if (str == NULL) {Py_INCREF(Py_None); return Py_None;}
38  
39     Dprintf("typecast_MXDATE_cast: s = %s", str);
40     
41     /* check for infinity */
42     if (!strcmp(str, "infinity") || !strcmp(str, "-infinity")) {
43         if (str[0] == '-') {
44             return mxDateTimeP->DateTime_FromDateAndTime(-999998,1,1, 0,0,0);
45         }
46         else {
47             return mxDateTimeP->DateTime_FromDateAndTime(999999,12,31, 0,0,0);
48         }
49     }
50     
51     n = typecast_parse_date(str, &tp, &len, &y, &m, &d);
52     Dprintf("typecast_MXDATE_cast: tp = %p n = %d, len = %d, "
53              "y = %d, m = %d, d = %d", tp, n, len, y, m, d);        
54     if (n != 3) {
55         PyErr_SetString(DataError, "unable to parse date");
56     }
57     
58     if (len > 0) {
59         n = typecast_parse_time(tp, NULL, &len, &hh, &mm, &ss, &us, &tz);
60         Dprintf("typecast_MXDATE_cast: n = %d, len = %d, "
61             "hh = %d, mm = %d, ss = %d, us = %d, tz = %d",
62             n, len, hh, mm, ss, us, tz);
63         if (n < 3 || n > 5) {
64             PyErr_SetString(DataError, "unable to parse time");
65         }
66     }    
67     
68     Dprintf("typecast_MXDATE_cast: fractionary seconds: %lf",
69         (double)ss + (double)us/(double)1000000.0);
70     return mxDateTimeP->DateTime_FromDateAndTime(y, m, d, hh, mm,
71         (double)ss + (double)us/(double)1000000.0);
72 }
73
74 /** TIME - parse time into an mx.DateTime object **/
75
76 static PyObject *
77 typecast_MXTIME_cast(char *str, int len, PyObject *curs)
78 {
79     int n, hh=0, mm=0, ss=0, us=0, tz=0;
80
81     if (str == NULL) {Py_INCREF(Py_None); return Py_None;}
82     
83     Dprintf("typecast_MXTIME_cast: s = %s", str);
84     
85     n = typecast_parse_time(str, NULL, &len, &hh, &mm, &ss, &us, &tz);
86     Dprintf("typecast_MXTIME_cast: time parsed, %d components", n);
87     Dprintf("typecast_MXTIME_cast: hh = %d, mm = %d, ss = %d, us = %d",
88              hh, mm, ss, us);
89     
90     if (n < 3 || n > 5) {
91         PyErr_SetString(DataError, "unable to parse time");
92         return NULL;
93     }
94
95     Dprintf("typecast_MXTIME_cast: fractionary seconds: %lf",
96         (double)ss + (double)us/(double)1000000.0);
97     return mxDateTimeP->DateTimeDelta_FromTime(hh, mm,
98         (double)ss + (double)us/(double)1000000.0);
99 }
100
101 /** INTERVAL - parse an interval into an mx.DateTimeDelta **/
102
103 static PyObject *
104 typecast_MXINTERVAL_cast(char *str, int len, PyObject *curs)
105 {
106     long years = 0, months = 0, days = 0, denominator = 1;
107     double hours = 0.0, minutes = 0.0, seconds = 0.0, hundredths = 0.0;
108     double v = 0.0, sign = 1.0;
109     int part = 0;
110
111     if (str == NULL) {Py_INCREF(Py_None); return Py_None;}
112     
113     Dprintf("typecast_MXINTERVAL_cast: s = %s", str);
114     
115     while (*str) {
116         switch (*str) {
117
118         case '-':
119             sign = -1.0;
120             break;
121
122         case '0': case '1': case '2': case '3': case '4':
123         case '5': case '6': case '7': case '8': case '9':
124             v = v*10 + (double)*str - (double)'0';
125             Dprintf("typecast_MXINTERVAL_cast: v = %f", v);
126             if (part == 6){
127                 denominator *= 10;
128                 Dprintf("typecast_MXINTERVAL_cast: denominator = %ld",
129                         denominator);
130             }
131             break;
132
133         case 'y':
134             if (part == 0) {
135                 years = (long)(v*sign);
136                 str = skip_until_space(str);
137                 Dprintf("typecast_MXINTERVAL_cast: years = %ld, rest = %s",
138                         years, str);
139                 v = 0.0; sign = 1.0; part = 1;
140             }
141             break;
142
143         case 'm':
144             if (part <= 1) {
145                 months = (long)(v*sign);
146                 str = skip_until_space(str);
147                 Dprintf("typecast_MXINTERVAL_cast: months = %ld, rest = %s",
148                         months, str);
149                 v = 0.0; sign = 1.0; part = 2;
150             }
151             break;
152
153         case 'd':
154             if (part <= 2) {
155                 days = (long)(v*sign);
156                 str = skip_until_space(str);
157                 Dprintf("typecast_MXINTERVAL_cast: days = %ld, rest = %s",
158                         days, str);
159                 v = 0.0; sign = 1.0; part = 3;
160             }
161             break;
162
163         case ':':
164             if (part <= 3) {
165                 hours = v;
166                 Dprintf("typecast_MXINTERVAL_cast: hours = %f", hours);
167                 v = 0.0; part = 4;
168             }
169             else if (part == 4) {
170                 minutes = v;
171                 Dprintf("typecast_MXINTERVAL_cast: minutes = %f", minutes);
172                 v = 0.0; part = 5;
173             }
174             break;
175
176         case '.':
177             if (part == 5) {
178                 seconds = v;
179                 Dprintf("typecast_MXINTERVAL_cast: seconds = %f", seconds);
180                 v = 0.0; part = 6;
181             }
182             break;   
183
184         default:
185             break;
186         }
187         
188         str++;
189     }
190
191     /* manage last value, be it minutes or seconds or hundredths of a second */
192     if (part == 4) {
193         minutes = v;
194         Dprintf("typecast_MXINTERVAL_cast: minutes = %f", minutes);
195     }
196     else if (part == 5) {
197         seconds = v;
198         Dprintf("typecast_MXINTERVAL_cast: seconds = %f", seconds);
199     }
200     else if (part == 6) {
201         hundredths = v;
202         Dprintf("typecast_MXINTERVAL_cast: hundredths = %f", hundredths);
203         hundredths = hundredths/denominator;
204         Dprintf("typecast_MXINTERVAL_cast: fractions = %.20f", hundredths);
205     }
206     
207     /* calculates seconds */
208     if (sign < 0.0) {
209         seconds = - (hundredths + seconds + minutes*60 + hours*3600);
210     }
211     else {
212         seconds += hundredths + minutes*60 + hours*3600;
213     }
214
215     /* calculates days */
216     days += years*365 + months*30;
217     
218     Dprintf("typecast_MXINTERVAL_cast: days = %ld, seconds = %f",
219             days, seconds);
220     return mxDateTimeP->DateTimeDelta_FromDaysAndSeconds(days, seconds);
221 }
222
223 /* psycopg defaults to using mx types */
224
225 #ifdef PSYCOPG_DEFAULT_MXDATETIME 
226 #define typecast_DATE_cast typecast_MXDATE_cast
227 #define typecast_TIME_cast typecast_MXTIME_cast
228 #define typecast_INTERVAL_cast typecast_MXINTERVAL_cast
229 #define typecast_DATETIME_cast typecast_MXDATE_cast
230 #endif
231