00001
00002
00003 #include "postgres_fe.h"
00004
00005 #include <time.h>
00006 #include <ctype.h>
00007 #include <math.h>
00008
00009 #include "extern.h"
00010 #include "dt.h"
00011 #include "pgtypes_timestamp.h"
00012
00013 int day_tab[2][13] = {
00014 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0},
00015 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0}};
00016
00017 typedef long AbsoluteTime;
00018
00019 #define ABS_SIGNBIT ((char) 0200)
00020 #define POS(n) (n)
00021 #define NEG(n) ((n)|ABS_SIGNBIT)
00022 #define FROMVAL(tp) (-SIGNEDCHAR((tp)->value) * 15)
00023 #define VALMASK ((char) 0177)
00024 #define SIGNEDCHAR(c) ((c)&ABS_SIGNBIT? -((c)&VALMASK): (c))
00025
00026 static datetkn datetktbl[] = {
00027
00028 {EARLY, RESERV, DTK_EARLY},
00029 {"acsst", DTZ, POS(42)},
00030 {"acst", DTZ, NEG(16)},
00031 {"act", TZ, NEG(20)},
00032 {DA_D, ADBC, AD},
00033 {"adt", DTZ, NEG(12)},
00034 {"aesst", DTZ, POS(44)},
00035 {"aest", TZ, POS(40)},
00036 {"aft", TZ, POS(18)},
00037 {"ahst", TZ, NEG(40)},
00038 {"akdt", DTZ, NEG(32)},
00039 {"akst", DTZ, NEG(36)},
00040 {"allballs", RESERV, DTK_ZULU},
00041 {"almst", TZ, POS(28)},
00042 {"almt", TZ, POS(24)},
00043 {"am", AMPM, AM},
00044 {"amst", DTZ, POS(20)},
00045 #if 0
00046 {"amst", DTZ, NEG(12)},
00047 #endif
00048 {"amt", TZ, POS(16)},
00049 {"anast", DTZ, POS(52)},
00050 {"anat", TZ, POS(48)},
00051 {"apr", MONTH, 4},
00052 {"april", MONTH, 4},
00053 #if 0
00054 aqtst
00055 aqtt
00056 arst
00057 #endif
00058 {"art", TZ, NEG(12)},
00059 #if 0
00060 ashst
00061 ast
00062
00063 #endif
00064 {"ast", TZ, NEG(16)},
00065 {"at", IGNORE_DTF, 0},
00066 {"aug", MONTH, 8},
00067 {"august", MONTH, 8},
00068 {"awsst", DTZ, POS(36)},
00069 {"awst", TZ, POS(32)},
00070 {"awt", DTZ, NEG(12)},
00071 {"azost", DTZ, POS(0)},
00072 {"azot", TZ, NEG(4)},
00073 {"azst", DTZ, POS(20)},
00074 {"azt", TZ, POS(16)},
00075 {DB_C, ADBC, BC},
00076 {"bdst", TZ, POS(8)},
00077 {"bdt", TZ, POS(24)},
00078 {"bnt", TZ, POS(32)},
00079 {"bort", TZ, POS(32)},
00080 #if 0
00081 bortst
00082 bost
00083 #endif
00084 {"bot", TZ, NEG(16)},
00085 {"bra", TZ, NEG(12)},
00086 #if 0
00087 brst
00088 brt
00089 #endif
00090 {"bst", DTZ, POS(4)},
00091 #if 0
00092 {"bst", TZ, NEG(12)},
00093 {"bst", DTZ, NEG(44)},
00094 #endif
00095 {"bt", TZ, POS(12)},
00096 {"btt", TZ, POS(24)},
00097 {"cadt", DTZ, POS(42)},
00098 {"cast", TZ, POS(38)},
00099 {"cat", TZ, NEG(40)},
00100 {"cct", TZ, POS(32)},
00101 #if 0
00102 {"cct", TZ, POS(26)},
00103 #endif
00104 {"cdt", DTZ, NEG(20)},
00105 {"cest", DTZ, POS(8)},
00106 {"cet", TZ, POS(4)},
00107 {"cetdst", DTZ, POS(8)},
00108 {"chadt", DTZ, POS(55)},
00109 {"chast", TZ, POS(51)},
00110 #if 0
00111 ckhst
00112 #endif
00113 {"ckt", TZ, POS(48)},
00114 {"clst", DTZ, NEG(12)},
00115 {"clt", TZ, NEG(16)},
00116 #if 0
00117 cost
00118 #endif
00119 {"cot", TZ, NEG(20)},
00120 {"cst", TZ, NEG(24)},
00121 {DCURRENT, RESERV, DTK_CURRENT},
00122 #if 0
00123 cvst
00124 #endif
00125 {"cvt", TZ, POS(28)},
00126 {"cxt", TZ, POS(28)},
00127 {"d", UNITS, DTK_DAY},
00128 {"davt", TZ, POS(28)},
00129 {"ddut", TZ, POS(40)},
00130 {"dec", MONTH, 12},
00131 {"december", MONTH, 12},
00132 {"dnt", TZ, POS(4)},
00133 {"dow", RESERV, DTK_DOW},
00134 {"doy", RESERV, DTK_DOY},
00135 {"dst", DTZMOD, 6},
00136 #if 0
00137 {"dusst", DTZ, POS(24)},
00138 #endif
00139 {"easst", DTZ, NEG(20)},
00140 {"east", TZ, NEG(24)},
00141 {"eat", TZ, POS(12)},
00142 #if 0
00143 {"east", DTZ, POS(16)},
00144 {"eat", TZ, POS(12)},
00145 {"ect", TZ, NEG(16)},
00146 {"ect", TZ, NEG(20)},
00147 #endif
00148 {"edt", DTZ, NEG(16)},
00149 {"eest", DTZ, POS(12)},
00150 {"eet", TZ, POS(8)},
00151 {"eetdst", DTZ, POS(12)},
00152 {"egst", DTZ, POS(0)},
00153 {"egt", TZ, NEG(4)},
00154 #if 0
00155 ehdt
00156 #endif
00157 {EPOCH, RESERV, DTK_EPOCH},
00158 {"est", TZ, NEG(20)},
00159 {"feb", MONTH, 2},
00160 {"february", MONTH, 2},
00161 {"fjst", DTZ, NEG(52)},
00162 {"fjt", TZ, NEG(48)},
00163 {"fkst", DTZ, NEG(12)},
00164 {"fkt", TZ, NEG(8)},
00165 #if 0
00166 fnst
00167 fnt
00168 #endif
00169 {"fri", DOW, 5},
00170 {"friday", DOW, 5},
00171 {"fst", TZ, POS(4)},
00172 {"fwt", DTZ, POS(8)},
00173 {"galt", TZ, NEG(24)},
00174 {"gamt", TZ, NEG(36)},
00175 {"gest", DTZ, POS(20)},
00176 {"get", TZ, POS(16)},
00177 {"gft", TZ, NEG(12)},
00178 #if 0
00179 ghst
00180 #endif
00181 {"gilt", TZ, POS(48)},
00182 {"gmt", TZ, POS(0)},
00183 {"gst", TZ, POS(40)},
00184 {"gyt", TZ, NEG(16)},
00185 {"h", UNITS, DTK_HOUR},
00186 #if 0
00187 hadt
00188 hast
00189 #endif
00190 {"hdt", DTZ, NEG(36)},
00191 #if 0
00192 hkst
00193 #endif
00194 {"hkt", TZ, POS(32)},
00195 #if 0
00196 {"hmt", TZ, POS(12)},
00197 hovst
00198 hovt
00199 #endif
00200 {"hst", TZ, NEG(40)},
00201 #if 0
00202 hwt
00203 #endif
00204 {"ict", TZ, POS(28)},
00205 {"idle", TZ, POS(48)},
00206 {"idlw", TZ, NEG(48)},
00207 #if 0
00208 idt
00209 #endif
00210 {LATE, RESERV, DTK_LATE},
00211 {INVALID, RESERV, DTK_INVALID},
00212 {"iot", TZ, POS(20)},
00213 {"irkst", DTZ, POS(36)},
00214 {"irkt", TZ, POS(32)},
00215 {"irt", TZ, POS(14)},
00216 {"isodow", RESERV, DTK_ISODOW},
00217 #if 0
00218 isst
00219 #endif
00220 {"ist", TZ, POS(8)},
00221 {"it", TZ, POS(14)},
00222 {"j", UNITS, DTK_JULIAN},
00223 {"jan", MONTH, 1},
00224 {"january", MONTH, 1},
00225 {"javt", TZ, POS(28)},
00226 {"jayt", TZ, POS(36)},
00227 {"jd", UNITS, DTK_JULIAN},
00228 {"jst", TZ, POS(36)},
00229 {"jt", TZ, POS(30)},
00230 {"jul", MONTH, 7},
00231 {"julian", UNITS, DTK_JULIAN},
00232 {"july", MONTH, 7},
00233 {"jun", MONTH, 6},
00234 {"june", MONTH, 6},
00235 {"kdt", DTZ, POS(40)},
00236 {"kgst", DTZ, POS(24)},
00237 {"kgt", TZ, POS(20)},
00238 {"kost", TZ, POS(48)},
00239 {"krast", DTZ, POS(28)},
00240 {"krat", TZ, POS(32)},
00241 {"kst", TZ, POS(36)},
00242 {"lhdt", DTZ, POS(44)},
00243 {"lhst", TZ, POS(42)},
00244 {"ligt", TZ, POS(40)},
00245 {"lint", TZ, POS(56)},
00246 {"lkt", TZ, POS(24)},
00247 {"m", UNITS, DTK_MONTH},
00248 {"magst", DTZ, POS(48)},
00249 {"magt", TZ, POS(44)},
00250 {"mar", MONTH, 3},
00251 {"march", MONTH, 3},
00252 {"mart", TZ, NEG(38)},
00253 {"mawt", TZ, POS(24)},
00254 {"may", MONTH, 5},
00255 {"mdt", DTZ, NEG(24)},
00256 {"mest", DTZ, POS(8)},
00257 {"met", TZ, POS(4)},
00258 {"metdst", DTZ, POS(8)},
00259 {"mewt", TZ, POS(4)},
00260 {"mez", TZ, POS(4)},
00261 {"mht", TZ, POS(48)},
00262 {"mm", UNITS, DTK_MINUTE},
00263 {"mmt", TZ, POS(26)},
00264 {"mon", DOW, 1},
00265 {"monday", DOW, 1},
00266 #if 0
00267 most
00268 #endif
00269 {"mpt", TZ, POS(40)},
00270 {"msd", DTZ, POS(16)},
00271 {"msk", TZ, POS(12)},
00272 {"mst", TZ, NEG(28)},
00273 {"mt", TZ, POS(34)},
00274 {"mut", TZ, POS(16)},
00275 {"mvt", TZ, POS(20)},
00276 {"myt", TZ, POS(32)},
00277 #if 0
00278 ncst
00279 #endif
00280 {"nct", TZ, POS(44)},
00281 {"ndt", DTZ, NEG(10)},
00282 {"nft", TZ, NEG(14)},
00283 {"nor", TZ, POS(4)},
00284 {"nov", MONTH, 11},
00285 {"november", MONTH, 11},
00286 {"novst", DTZ, POS(28)},
00287 {"novt", TZ, POS(24)},
00288 {NOW, RESERV, DTK_NOW},
00289 {"npt", TZ, POS(23)},
00290 {"nst", TZ, NEG(14)},
00291 {"nt", TZ, NEG(44)},
00292 {"nut", TZ, NEG(44)},
00293 {"nzdt", DTZ, POS(52)},
00294 {"nzst", TZ, POS(48)},
00295 {"nzt", TZ, POS(48)},
00296 {"oct", MONTH, 10},
00297 {"october", MONTH, 10},
00298 {"omsst", DTZ, POS(28)},
00299 {"omst", TZ, POS(24)},
00300 {"on", IGNORE_DTF, 0},
00301 {"pdt", DTZ, NEG(28)},
00302 #if 0
00303 pest
00304 #endif
00305 {"pet", TZ, NEG(20)},
00306 {"petst", DTZ, POS(52)},
00307 {"pett", TZ, POS(48)},
00308 {"pgt", TZ, POS(40)},
00309 {"phot", TZ, POS(52)},
00310 #if 0
00311 phst
00312 #endif
00313 {"pht", TZ, POS(32)},
00314 {"pkt", TZ, POS(20)},
00315 {"pm", AMPM, PM},
00316 {"pmdt", DTZ, NEG(8)},
00317 #if 0
00318 pmst
00319 #endif
00320 {"pont", TZ, POS(44)},
00321 {"pst", TZ, NEG(32)},
00322 {"pwt", TZ, POS(36)},
00323 {"pyst", DTZ, NEG(12)},
00324 {"pyt", TZ, NEG(16)},
00325 {"ret", DTZ, POS(16)},
00326 {"s", UNITS, DTK_SECOND},
00327 {"sadt", DTZ, POS(42)},
00328 #if 0
00329 samst
00330 samt
00331 #endif
00332 {"sast", TZ, POS(38)},
00333 {"sat", DOW, 6},
00334 {"saturday", DOW, 6},
00335 #if 0
00336 sbt
00337 #endif
00338 {"sct", DTZ, POS(16)},
00339 {"sep", MONTH, 9},
00340 {"sept", MONTH, 9},
00341 {"september", MONTH, 9},
00342 {"set", TZ, NEG(4)},
00343 #if 0
00344 sgt
00345 #endif
00346 {"sst", DTZ, POS(8)},
00347 {"sun", DOW, 0},
00348 {"sunday", DOW, 0},
00349 {"swt", TZ, POS(4)},
00350 #if 0
00351 syot
00352 #endif
00353 {"t", ISOTIME, DTK_TIME},
00354 {"tft", TZ, POS(20)},
00355 {"that", TZ, NEG(40)},
00356 {"thu", DOW, 4},
00357 {"thur", DOW, 4},
00358 {"thurs", DOW, 4},
00359 {"thursday", DOW, 4},
00360 {"tjt", TZ, POS(20)},
00361 {"tkt", TZ, NEG(40)},
00362 {"tmt", TZ, POS(20)},
00363 {TODAY, RESERV, DTK_TODAY},
00364 {TOMORROW, RESERV, DTK_TOMORROW},
00365 #if 0
00366 tost
00367 #endif
00368 {"tot", TZ, POS(52)},
00369 #if 0
00370 tpt
00371 #endif
00372 {"truk", TZ, POS(40)},
00373 {"tue", DOW, 2},
00374 {"tues", DOW, 2},
00375 {"tuesday", DOW, 2},
00376 {"tvt", TZ, POS(48)},
00377 #if 0
00378 uct
00379 #endif
00380 {"ulast", DTZ, POS(36)},
00381 {"ulat", TZ, POS(32)},
00382 {"undefined", RESERV, DTK_INVALID},
00383 {"ut", TZ, POS(0)},
00384 {"utc", TZ, POS(0)},
00385 {"uyst", DTZ, NEG(8)},
00386 {"uyt", TZ, NEG(12)},
00387 {"uzst", DTZ, POS(24)},
00388 {"uzt", TZ, POS(20)},
00389 {"vet", TZ, NEG(16)},
00390 {"vlast", DTZ, POS(44)},
00391 {"vlat", TZ, POS(40)},
00392 #if 0
00393 vust
00394 #endif
00395 {"vut", TZ, POS(44)},
00396 {"wadt", DTZ, POS(32)},
00397 {"wakt", TZ, POS(48)},
00398 #if 0
00399 warst
00400 #endif
00401 {"wast", TZ, POS(28)},
00402 {"wat", TZ, NEG(4)},
00403 {"wdt", DTZ, POS(36)},
00404 {"wed", DOW, 3},
00405 {"wednesday", DOW, 3},
00406 {"weds", DOW, 3},
00407 {"west", DTZ, POS(4)},
00408 {"wet", TZ, POS(0)},
00409 {"wetdst", DTZ, POS(4)},
00410 {"wft", TZ, POS(48)},
00411 {"wgst", DTZ, NEG(8)},
00412 {"wgt", TZ, NEG(12)},
00413 {"wst", TZ, POS(32)},
00414 {"y", UNITS, DTK_YEAR},
00415 {"yakst", DTZ, POS(40)},
00416 {"yakt", TZ, POS(36)},
00417 {"yapt", TZ, POS(40)},
00418 {"ydt", DTZ, NEG(32)},
00419 {"yekst", DTZ, POS(24)},
00420 {"yekt", TZ, POS(20)},
00421 {YESTERDAY, RESERV, DTK_YESTERDAY},
00422 {"yst", TZ, NEG(36)},
00423 {"z", TZ, POS(0)},
00424 {"zp4", TZ, NEG(16)},
00425 {"zp5", TZ, NEG(20)},
00426 {"zp6", TZ, NEG(24)},
00427 {ZULU, TZ, POS(0)},
00428 };
00429
00430 static datetkn deltatktbl[] = {
00431
00432 {"@", IGNORE_DTF, 0},
00433 {DAGO, AGO, 0},
00434 {"c", UNITS, DTK_CENTURY},
00435 {"cent", UNITS, DTK_CENTURY},
00436 {"centuries", UNITS, DTK_CENTURY},
00437 {DCENTURY, UNITS, DTK_CENTURY},
00438 {"d", UNITS, DTK_DAY},
00439 {DDAY, UNITS, DTK_DAY},
00440 {"days", UNITS, DTK_DAY},
00441 {"dec", UNITS, DTK_DECADE},
00442 {DDECADE, UNITS, DTK_DECADE},
00443 {"decades", UNITS, DTK_DECADE},
00444 {"decs", UNITS, DTK_DECADE},
00445 {"h", UNITS, DTK_HOUR},
00446 {DHOUR, UNITS, DTK_HOUR},
00447 {"hours", UNITS, DTK_HOUR},
00448 {"hr", UNITS, DTK_HOUR},
00449 {"hrs", UNITS, DTK_HOUR},
00450 {INVALID, RESERV, DTK_INVALID},
00451 {"m", UNITS, DTK_MINUTE},
00452 {"microsecon", UNITS, DTK_MICROSEC},
00453 {"mil", UNITS, DTK_MILLENNIUM},
00454 {"millennia", UNITS, DTK_MILLENNIUM},
00455 {DMILLENNIUM, UNITS, DTK_MILLENNIUM},
00456 {"millisecon", UNITS, DTK_MILLISEC},
00457 {"mils", UNITS, DTK_MILLENNIUM},
00458 {"min", UNITS, DTK_MINUTE},
00459 {"mins", UNITS, DTK_MINUTE},
00460 {DMINUTE, UNITS, DTK_MINUTE},
00461 {"minutes", UNITS, DTK_MINUTE},
00462 {"mon", UNITS, DTK_MONTH},
00463 {"mons", UNITS, DTK_MONTH},
00464 {DMONTH, UNITS, DTK_MONTH},
00465 {"months", UNITS, DTK_MONTH},
00466 {"ms", UNITS, DTK_MILLISEC},
00467 {"msec", UNITS, DTK_MILLISEC},
00468 {DMILLISEC, UNITS, DTK_MILLISEC},
00469 {"mseconds", UNITS, DTK_MILLISEC},
00470 {"msecs", UNITS, DTK_MILLISEC},
00471 {"qtr", UNITS, DTK_QUARTER},
00472 {DQUARTER, UNITS, DTK_QUARTER},
00473 {"s", UNITS, DTK_SECOND},
00474 {"sec", UNITS, DTK_SECOND},
00475 {DSECOND, UNITS, DTK_SECOND},
00476 {"seconds", UNITS, DTK_SECOND},
00477 {"secs", UNITS, DTK_SECOND},
00478 {DTIMEZONE, UNITS, DTK_TZ},
00479 {"timezone_h", UNITS, DTK_TZ_HOUR},
00480 {"timezone_m", UNITS, DTK_TZ_MINUTE},
00481 {"undefined", RESERV, DTK_INVALID},
00482 {"us", UNITS, DTK_MICROSEC},
00483 {"usec", UNITS, DTK_MICROSEC},
00484 {DMICROSEC, UNITS, DTK_MICROSEC},
00485 {"useconds", UNITS, DTK_MICROSEC},
00486 {"usecs", UNITS, DTK_MICROSEC},
00487 {"w", UNITS, DTK_WEEK},
00488 {DWEEK, UNITS, DTK_WEEK},
00489 {"weeks", UNITS, DTK_WEEK},
00490 {"y", UNITS, DTK_YEAR},
00491 {DYEAR, UNITS, DTK_YEAR},
00492 {"years", UNITS, DTK_YEAR},
00493 {"yr", UNITS, DTK_YEAR},
00494 {"yrs", UNITS, DTK_YEAR},
00495 };
00496
00497 static const unsigned int szdatetktbl = lengthof(datetktbl);
00498 static const unsigned int szdeltatktbl = lengthof(deltatktbl);
00499
00500 static datetkn *datecache[MAXDATEFIELDS] = {NULL};
00501
00502 static datetkn *deltacache[MAXDATEFIELDS] = {NULL};
00503
00504 char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL};
00505
00506 char *days[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", NULL};
00507
00508 char *pgtypes_date_weekdays_short[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL};
00509
00510 char *pgtypes_date_months[] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", NULL};
00511
00512 static datetkn *
00513 datebsearch(char *key, datetkn *base, unsigned int nel)
00514 {
00515 if (nel > 0)
00516 {
00517 datetkn *last = base + nel - 1,
00518 *position;
00519 int result;
00520
00521 while (last >= base)
00522 {
00523 position = base + ((last - base) >> 1);
00524 result = key[0] - position->token[0];
00525 if (result == 0)
00526 {
00527 result = strncmp(key, position->token, TOKMAXLEN);
00528 if (result == 0)
00529 return position;
00530 }
00531 if (result < 0)
00532 last = position - 1;
00533 else
00534 base = position + 1;
00535 }
00536 }
00537 return NULL;
00538 }
00539
00540
00541
00542
00543
00544 int
00545 DecodeUnits(int field, char *lowtoken, int *val)
00546 {
00547 int type;
00548 datetkn *tp;
00549
00550 if (deltacache[field] != NULL &&
00551 strncmp(lowtoken, deltacache[field]->token, TOKMAXLEN) == 0)
00552 tp = deltacache[field];
00553 else
00554 tp = datebsearch(lowtoken, deltatktbl, szdeltatktbl);
00555 deltacache[field] = tp;
00556 if (tp == NULL)
00557 {
00558 type = UNKNOWN_FIELD;
00559 *val = 0;
00560 }
00561 else
00562 {
00563 type = tp->type;
00564 if (type == TZ || type == DTZ)
00565 *val = FROMVAL(tp);
00566 else
00567 *val = tp->value;
00568 }
00569
00570 return type;
00571 }
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591 int
00592 date2j(int y, int m, int d)
00593 {
00594 int julian;
00595 int century;
00596
00597 if (m > 2)
00598 {
00599 m += 1;
00600 y += 4800;
00601 }
00602 else
00603 {
00604 m += 13;
00605 y += 4799;
00606 }
00607
00608 century = y / 100;
00609 julian = y * 365 - 32167;
00610 julian += y / 4 - century + century / 4;
00611 julian += 7834 * m / 256 + d;
00612
00613 return julian;
00614 }
00615
00616 void
00617 j2date(int jd, int *year, int *month, int *day)
00618 {
00619 unsigned int julian;
00620 unsigned int quad;
00621 unsigned int extra;
00622 int y;
00623
00624 julian = jd;
00625 julian += 32044;
00626 quad = julian / 146097;
00627 extra = (julian - quad * 146097) * 4 + 3;
00628 julian += 60 + quad * 3 + extra / 146097;
00629 quad = julian / 1461;
00630 julian -= quad * 1461;
00631 y = julian * 4 / 1461;
00632 julian = ((y != 0) ? (julian + 305) % 365 : (julian + 306) % 366) + 123;
00633 y += quad * 4;
00634 *year = y - 4800;
00635 quad = julian * 2141 / 65536;
00636 *day = julian - 7834 * quad / 256;
00637 *month = (quad + 10) % 12 + 1;
00638
00639 return;
00640 }
00641
00642
00643
00644
00645
00646
00647 static int
00648 DecodeSpecial(int field, char *lowtoken, int *val)
00649 {
00650 int type;
00651 datetkn *tp;
00652
00653 if (datecache[field] != NULL &&
00654 strncmp(lowtoken, datecache[field]->token, TOKMAXLEN) == 0)
00655 tp = datecache[field];
00656 else
00657 {
00658 tp = NULL;
00659 if (!tp)
00660 tp = datebsearch(lowtoken, datetktbl, szdatetktbl);
00661 }
00662 datecache[field] = tp;
00663 if (tp == NULL)
00664 {
00665 type = UNKNOWN_FIELD;
00666 *val = 0;
00667 }
00668 else
00669 {
00670 type = tp->type;
00671 switch (type)
00672 {
00673 case TZ:
00674 case DTZ:
00675 case DTZMOD:
00676 *val = FROMVAL(tp);
00677 break;
00678
00679 default:
00680 *val = tp->value;
00681 break;
00682 }
00683 }
00684
00685 return type;
00686 }
00687
00688
00689
00690
00691 int
00692 EncodeDateOnly(struct tm * tm, int style, char *str, bool EuroDates)
00693 {
00694 if (tm->tm_mon < 1 || tm->tm_mon > MONTHS_PER_YEAR)
00695 return -1;
00696
00697 switch (style)
00698 {
00699 case USE_ISO_DATES:
00700
00701 if (tm->tm_year > 0)
00702 sprintf(str, "%04d-%02d-%02d",
00703 tm->tm_year, tm->tm_mon, tm->tm_mday);
00704 else
00705 sprintf(str, "%04d-%02d-%02d %s",
00706 -(tm->tm_year - 1), tm->tm_mon, tm->tm_mday, "BC");
00707 break;
00708
00709 case USE_SQL_DATES:
00710
00711 if (EuroDates)
00712 sprintf(str, "%02d/%02d", tm->tm_mday, tm->tm_mon);
00713 else
00714 sprintf(str, "%02d/%02d", tm->tm_mon, tm->tm_mday);
00715 if (tm->tm_year > 0)
00716 sprintf(str + 5, "/%04d", tm->tm_year);
00717 else
00718 sprintf(str + 5, "/%04d %s", -(tm->tm_year - 1), "BC");
00719 break;
00720
00721 case USE_GERMAN_DATES:
00722
00723 sprintf(str, "%02d.%02d", tm->tm_mday, tm->tm_mon);
00724 if (tm->tm_year > 0)
00725 sprintf(str + 5, ".%04d", tm->tm_year);
00726 else
00727 sprintf(str + 5, ".%04d %s", -(tm->tm_year - 1), "BC");
00728 break;
00729
00730 case USE_POSTGRES_DATES:
00731 default:
00732
00733 if (EuroDates)
00734 sprintf(str, "%02d-%02d", tm->tm_mday, tm->tm_mon);
00735 else
00736 sprintf(str, "%02d-%02d", tm->tm_mon, tm->tm_mday);
00737 if (tm->tm_year > 0)
00738 sprintf(str + 5, "-%04d", tm->tm_year);
00739 else
00740 sprintf(str + 5, "-%04d %s", -(tm->tm_year - 1), "BC");
00741 break;
00742 }
00743
00744 return TRUE;
00745 }
00746
00747 void
00748 TrimTrailingZeros(char *str)
00749 {
00750 int len = strlen(str);
00751
00752
00753 while (*(str + len - 1) == '0' && *(str + len - 3) != '.')
00754 {
00755 len--;
00756 *(str + len) = '\0';
00757 }
00758 }
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778 int
00779 EncodeDateTime(struct tm * tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str, bool EuroDates)
00780 {
00781 int day,
00782 hour,
00783 min;
00784
00785
00786
00787
00788 if (tm->tm_isdst < 0)
00789 print_tz = false;
00790
00791 switch (style)
00792 {
00793 case USE_ISO_DATES:
00794
00795
00796 sprintf(str, "%04d-%02d-%02d %02d:%02d",
00797 (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1),
00798 tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min);
00799
00800
00801
00802
00803
00804
00805
00806
00807 #ifdef HAVE_INT64_TIMESTAMP
00808 if (fsec != 0)
00809 {
00810 sprintf(str + strlen(str), ":%02d.%06d", tm->tm_sec, fsec);
00811 #else
00812 if ((fsec != 0) && (tm->tm_year > 0))
00813 {
00814 sprintf(str + strlen(str), ":%09.6f", tm->tm_sec + fsec);
00815 #endif
00816 TrimTrailingZeros(str);
00817 }
00818 else
00819 sprintf(str + strlen(str), ":%02d", tm->tm_sec);
00820
00821 if (tm->tm_year <= 0)
00822 sprintf(str + strlen(str), " BC");
00823
00824 if (print_tz)
00825 {
00826 hour = -(tz / SECS_PER_HOUR);
00827 min = (abs(tz) / MINS_PER_HOUR) % MINS_PER_HOUR;
00828 if (min != 0)
00829 sprintf(str + strlen(str), "%+03d:%02d", hour, min);
00830 else
00831 sprintf(str + strlen(str), "%+03d", hour);
00832 }
00833 break;
00834
00835 case USE_SQL_DATES:
00836
00837
00838 if (EuroDates)
00839 sprintf(str, "%02d/%02d", tm->tm_mday, tm->tm_mon);
00840 else
00841 sprintf(str, "%02d/%02d", tm->tm_mon, tm->tm_mday);
00842
00843 sprintf(str + 5, "/%04d %02d:%02d",
00844 (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1),
00845 tm->tm_hour, tm->tm_min);
00846
00847
00848
00849
00850
00851
00852
00853
00854 #ifdef HAVE_INT64_TIMESTAMP
00855 if (fsec != 0)
00856 {
00857 sprintf(str + strlen(str), ":%02d.%06d", tm->tm_sec, fsec);
00858 #else
00859 if (fsec != 0 && tm->tm_year > 0)
00860 {
00861 sprintf(str + strlen(str), ":%09.6f", tm->tm_sec + fsec);
00862 #endif
00863 TrimTrailingZeros(str);
00864 }
00865 else
00866 sprintf(str + strlen(str), ":%02d", tm->tm_sec);
00867
00868 if (tm->tm_year <= 0)
00869 sprintf(str + strlen(str), " BC");
00870
00871
00872
00873
00874
00875
00876
00877 if (print_tz)
00878 {
00879 if (tzn)
00880 sprintf(str + strlen(str), " %.*s", MAXTZLEN, tzn);
00881 else
00882 {
00883 hour = -(tz / SECS_PER_HOUR);
00884 min = (abs(tz) / MINS_PER_HOUR) % MINS_PER_HOUR;
00885 if (min != 0)
00886 sprintf(str + strlen(str), "%+03d:%02d", hour, min);
00887 else
00888 sprintf(str + strlen(str), "%+03d", hour);
00889 }
00890 }
00891 break;
00892
00893 case USE_GERMAN_DATES:
00894
00895
00896 sprintf(str, "%02d.%02d", tm->tm_mday, tm->tm_mon);
00897
00898 sprintf(str + 5, ".%04d %02d:%02d",
00899 (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1),
00900 tm->tm_hour, tm->tm_min);
00901
00902
00903
00904
00905
00906
00907
00908
00909 #ifdef HAVE_INT64_TIMESTAMP
00910 if (fsec != 0)
00911 {
00912 sprintf(str + strlen(str), ":%02d.%06d", tm->tm_sec, fsec);
00913 #else
00914 if (fsec != 0 && tm->tm_year > 0)
00915 {
00916 sprintf(str + strlen(str), ":%09.6f", tm->tm_sec + fsec);
00917 #endif
00918 TrimTrailingZeros(str);
00919 }
00920 else
00921 sprintf(str + strlen(str), ":%02d", tm->tm_sec);
00922
00923 if (tm->tm_year <= 0)
00924 sprintf(str + strlen(str), " BC");
00925
00926 if (print_tz)
00927 {
00928 if (tzn)
00929 sprintf(str + strlen(str), " %.*s", MAXTZLEN, tzn);
00930 else
00931 {
00932 hour = -(tz / SECS_PER_HOUR);
00933 min = (abs(tz) / MINS_PER_HOUR) % MINS_PER_HOUR;
00934 if (min != 0)
00935 sprintf(str + strlen(str), "%+03d:%02d", hour, min);
00936 else
00937 sprintf(str + strlen(str), "%+03d", hour);
00938 }
00939 }
00940 break;
00941
00942 case USE_POSTGRES_DATES:
00943 default:
00944
00945
00946 day = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday);
00947 tm->tm_wday = (int) ((day + date2j(2000, 1, 1) + 1) % 7);
00948
00949 strncpy(str, days[tm->tm_wday], 3);
00950 strcpy(str + 3, " ");
00951
00952 if (EuroDates)
00953 sprintf(str + 4, "%02d %3s", tm->tm_mday, months[tm->tm_mon - 1]);
00954 else
00955 sprintf(str + 4, "%3s %02d", months[tm->tm_mon - 1], tm->tm_mday);
00956
00957 sprintf(str + 10, " %02d:%02d", tm->tm_hour, tm->tm_min);
00958
00959
00960
00961
00962
00963
00964
00965
00966 #ifdef HAVE_INT64_TIMESTAMP
00967 if (fsec != 0)
00968 {
00969 sprintf(str + strlen(str), ":%02d.%06d", tm->tm_sec, fsec);
00970 #else
00971 if (fsec != 0 && tm->tm_year > 0)
00972 {
00973 sprintf(str + strlen(str), ":%09.6f", tm->tm_sec + fsec);
00974 #endif
00975 TrimTrailingZeros(str);
00976 }
00977 else
00978 sprintf(str + strlen(str), ":%02d", tm->tm_sec);
00979
00980 sprintf(str + strlen(str), " %04d",
00981 (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1));
00982 if (tm->tm_year <= 0)
00983 sprintf(str + strlen(str), " BC");
00984
00985 if (print_tz)
00986 {
00987 if (tzn)
00988 sprintf(str + strlen(str), " %.*s", MAXTZLEN, tzn);
00989 else
00990 {
00991
00992
00993
00994
00995
00996
00997 hour = -(tz / SECS_PER_HOUR);
00998 min = (abs(tz) / MINS_PER_HOUR) % MINS_PER_HOUR;
00999 if (min != 0)
01000 sprintf(str + strlen(str), " %+03d:%02d", hour, min);
01001 else
01002 sprintf(str + strlen(str), " %+03d", hour);
01003 }
01004 }
01005 break;
01006 }
01007
01008 return TRUE;
01009 }
01010
01011 int
01012 GetEpochTime(struct tm * tm)
01013 {
01014 struct tm *t0;
01015 time_t epoch = 0;
01016
01017 t0 = gmtime(&epoch);
01018
01019 if (t0)
01020 {
01021 tm->tm_year = t0->tm_year + 1900;
01022 tm->tm_mon = t0->tm_mon + 1;
01023 tm->tm_mday = t0->tm_mday;
01024 tm->tm_hour = t0->tm_hour;
01025 tm->tm_min = t0->tm_min;
01026 tm->tm_sec = t0->tm_sec;
01027
01028 return 0;
01029 }
01030
01031 return -1;
01032 }
01033
01034 static void
01035 abstime2tm(AbsoluteTime _time, int *tzp, struct tm * tm, char **tzn)
01036 {
01037 time_t time = (time_t) _time;
01038 struct tm *tx;
01039
01040 errno = 0;
01041 if (tzp != NULL)
01042 tx = localtime((time_t *) &time);
01043 else
01044 tx = gmtime((time_t *) &time);
01045
01046 if (!tx)
01047 {
01048 errno = PGTYPES_TS_BAD_TIMESTAMP;
01049 return;
01050 }
01051
01052 tm->tm_year = tx->tm_year + 1900;
01053 tm->tm_mon = tx->tm_mon + 1;
01054 tm->tm_mday = tx->tm_mday;
01055 tm->tm_hour = tx->tm_hour;
01056 tm->tm_min = tx->tm_min;
01057 tm->tm_sec = tx->tm_sec;
01058 tm->tm_isdst = tx->tm_isdst;
01059
01060 #if defined(HAVE_TM_ZONE)
01061 tm->tm_gmtoff = tx->tm_gmtoff;
01062 tm->tm_zone = tx->tm_zone;
01063
01064 if (tzp != NULL)
01065 {
01066
01067
01068
01069
01070 *tzp = -tm->tm_gmtoff;
01071
01072
01073
01074
01075 if (tzn != NULL)
01076 {
01077
01078
01079
01080
01081 StrNCpy(*tzn, tm->tm_zone, MAXTZLEN + 1);
01082 if (strlen(tm->tm_zone) > MAXTZLEN)
01083 tm->tm_isdst = -1;
01084 }
01085 }
01086 else
01087 tm->tm_isdst = -1;
01088 #elif defined(HAVE_INT_TIMEZONE)
01089 if (tzp != NULL)
01090 {
01091 *tzp = (tm->tm_isdst > 0) ? TIMEZONE_GLOBAL - SECS_PER_HOUR : TIMEZONE_GLOBAL;
01092
01093 if (tzn != NULL)
01094 {
01095
01096
01097
01098
01099 StrNCpy(*tzn, TZNAME_GLOBAL[tm->tm_isdst], MAXTZLEN + 1);
01100 if (strlen(TZNAME_GLOBAL[tm->tm_isdst]) > MAXTZLEN)
01101 tm->tm_isdst = -1;
01102 }
01103 }
01104 else
01105 tm->tm_isdst = -1;
01106 #else
01107 if (tzp != NULL)
01108 {
01109
01110 *tzp = 0;
01111 if (tzn != NULL)
01112 *tzn = NULL;
01113 }
01114 else
01115 tm->tm_isdst = -1;
01116 #endif
01117 }
01118
01119 void
01120 GetCurrentDateTime(struct tm * tm)
01121 {
01122 int tz;
01123
01124 abstime2tm(time(NULL), &tz, tm, NULL);
01125 }
01126
01127 void
01128 dt2time(double jd, int *hour, int *min, int *sec, fsec_t *fsec)
01129 {
01130 #ifdef HAVE_INT64_TIMESTAMP
01131 int64 time;
01132 #else
01133 double time;
01134 #endif
01135
01136 time = jd;
01137 #ifdef HAVE_INT64_TIMESTAMP
01138 *hour = time / USECS_PER_HOUR;
01139 time -= (*hour) * USECS_PER_HOUR;
01140 *min = time / USECS_PER_MINUTE;
01141 time -= (*min) * USECS_PER_MINUTE;
01142 *sec = time / USECS_PER_SEC;
01143 *fsec = time - (*sec * USECS_PER_SEC);
01144 #else
01145 *hour = time / SECS_PER_HOUR;
01146 time -= (*hour) * SECS_PER_HOUR;
01147 *min = time / SECS_PER_MINUTE;
01148 time -= (*min) * SECS_PER_MINUTE;
01149 *sec = time;
01150 *fsec = time - *sec;
01151 #endif
01152 }
01153
01154
01155
01156
01157
01158
01159
01160
01161 static int
01162 DecodeNumberField(int len, char *str, int fmask,
01163 int *tmask, struct tm * tm, fsec_t *fsec, int *is2digits)
01164 {
01165 char *cp;
01166
01167
01168
01169
01170
01171 if ((cp = strchr(str, '.')) != NULL)
01172 {
01173 #ifdef HAVE_INT64_TIMESTAMP
01174 char fstr[MAXDATELEN + 1];
01175
01176
01177
01178
01179
01180 strcpy(fstr, (cp + 1));
01181 strcpy(fstr + strlen(fstr), "000000");
01182 *(fstr + 6) = '\0';
01183 *fsec = strtol(fstr, NULL, 10);
01184 #else
01185 *fsec = strtod(cp, NULL);
01186 #endif
01187 *cp = '\0';
01188 len = strlen(str);
01189 }
01190
01191 else if ((fmask & DTK_DATE_M) != DTK_DATE_M)
01192 {
01193
01194 if (len == 8)
01195 {
01196 *tmask = DTK_DATE_M;
01197
01198 tm->tm_mday = atoi(str + 6);
01199 *(str + 6) = '\0';
01200 tm->tm_mon = atoi(str + 4);
01201 *(str + 4) = '\0';
01202 tm->tm_year = atoi(str + 0);
01203
01204 return DTK_DATE;
01205 }
01206
01207 else if (len == 6)
01208 {
01209 *tmask = DTK_DATE_M;
01210 tm->tm_mday = atoi(str + 4);
01211 *(str + 4) = '\0';
01212 tm->tm_mon = atoi(str + 2);
01213 *(str + 2) = '\0';
01214 tm->tm_year = atoi(str + 0);
01215 *is2digits = TRUE;
01216
01217 return DTK_DATE;
01218 }
01219
01220 else if (len == 5)
01221 {
01222 *tmask = DTK_DATE_M;
01223 tm->tm_mday = atoi(str + 2);
01224 *(str + 2) = '\0';
01225 tm->tm_mon = 1;
01226 tm->tm_year = atoi(str + 0);
01227 *is2digits = TRUE;
01228
01229 return DTK_DATE;
01230 }
01231 }
01232
01233
01234 if ((fmask & DTK_TIME_M) != DTK_TIME_M)
01235 {
01236
01237 if (len == 6)
01238 {
01239 *tmask = DTK_TIME_M;
01240 tm->tm_sec = atoi(str + 4);
01241 *(str + 4) = '\0';
01242 tm->tm_min = atoi(str + 2);
01243 *(str + 2) = '\0';
01244 tm->tm_hour = atoi(str + 0);
01245
01246 return DTK_TIME;
01247 }
01248
01249 else if (len == 4)
01250 {
01251 *tmask = DTK_TIME_M;
01252 tm->tm_sec = 0;
01253 tm->tm_min = atoi(str + 2);
01254 *(str + 2) = '\0';
01255 tm->tm_hour = atoi(str + 0);
01256
01257 return DTK_TIME;
01258 }
01259 }
01260
01261 return -1;
01262 }
01263
01264
01265
01266
01267
01268 static int
01269 DecodeNumber(int flen, char *str, int fmask,
01270 int *tmask, struct tm * tm, fsec_t *fsec, int *is2digits, bool EuroDates)
01271 {
01272 int val;
01273 char *cp;
01274
01275 *tmask = 0;
01276
01277 val = strtol(str, &cp, 10);
01278 if (cp == str)
01279 return -1;
01280
01281 if (*cp == '.')
01282 {
01283
01284
01285
01286
01287 if (cp - str > 2)
01288 return DecodeNumberField(flen, str, (fmask | DTK_DATE_M),
01289 tmask, tm, fsec, is2digits);
01290
01291 *fsec = strtod(cp, &cp);
01292 if (*cp != '\0')
01293 return -1;
01294 }
01295 else if (*cp != '\0')
01296 return -1;
01297
01298
01299 if (flen == 3 && (fmask & DTK_M(YEAR)) && val >= 1 && val <= 366)
01300 {
01301 *tmask = (DTK_M(DOY) | DTK_M(MONTH) | DTK_M(DAY));
01302 tm->tm_yday = val;
01303 j2date(date2j(tm->tm_year, 1, 1) + tm->tm_yday - 1,
01304 &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
01305 }
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315 else if (flen >= 4)
01316 {
01317 *tmask = DTK_M(YEAR);
01318
01319
01320 if ((fmask & DTK_M(YEAR)) && !(fmask & DTK_M(DAY)) &&
01321 tm->tm_year >= 1 && tm->tm_year <= 31)
01322 {
01323 tm->tm_mday = tm->tm_year;
01324 *tmask = DTK_M(DAY);
01325 }
01326
01327 tm->tm_year = val;
01328 }
01329
01330
01331 else if ((fmask & DTK_M(YEAR)) && !(fmask & DTK_M(MONTH)) && val >= 1 && val <= MONTHS_PER_YEAR)
01332 {
01333 *tmask = DTK_M(MONTH);
01334 tm->tm_mon = val;
01335 }
01336
01337 else if ((EuroDates || (fmask & DTK_M(MONTH))) &&
01338 !(fmask & DTK_M(YEAR)) && !(fmask & DTK_M(DAY)) &&
01339 val >= 1 && val <= 31)
01340 {
01341 *tmask = DTK_M(DAY);
01342 tm->tm_mday = val;
01343 }
01344 else if (!(fmask & DTK_M(MONTH)) && val >= 1 && val <= MONTHS_PER_YEAR)
01345 {
01346 *tmask = DTK_M(MONTH);
01347 tm->tm_mon = val;
01348 }
01349 else if (!(fmask & DTK_M(DAY)) && val >= 1 && val <= 31)
01350 {
01351 *tmask = DTK_M(DAY);
01352 tm->tm_mday = val;
01353 }
01354
01355
01356
01357
01358
01359 else if (!(fmask & DTK_M(YEAR)) && (flen >= 4 || flen == 2))
01360 {
01361 *tmask = DTK_M(YEAR);
01362 tm->tm_year = val;
01363
01364
01365 *is2digits = (flen == 2);
01366 }
01367 else
01368 return -1;
01369
01370 return 0;
01371 }
01372
01373
01374
01375
01376
01377 static int
01378 DecodeDate(char *str, int fmask, int *tmask, struct tm * tm, bool EuroDates)
01379 {
01380 fsec_t fsec;
01381
01382 int nf = 0;
01383 int i,
01384 len;
01385 int bc = FALSE;
01386 int is2digits = FALSE;
01387 int type,
01388 val,
01389 dmask = 0;
01390 char *field[MAXDATEFIELDS];
01391
01392
01393 while (*str != '\0' && nf < MAXDATEFIELDS)
01394 {
01395
01396 while (!isalnum((unsigned char) *str))
01397 str++;
01398
01399 field[nf] = str;
01400 if (isdigit((unsigned char) *str))
01401 {
01402 while (isdigit((unsigned char) *str))
01403 str++;
01404 }
01405 else if (isalpha((unsigned char) *str))
01406 {
01407 while (isalpha((unsigned char) *str))
01408 str++;
01409 }
01410
01411
01412 if (*str != '\0')
01413 *str++ = '\0';
01414 nf++;
01415 }
01416
01417 #if 0
01418
01419 if (nf > 3)
01420 return -1;
01421 #endif
01422
01423 *tmask = 0;
01424
01425
01426 for (i = 0; i < nf; i++)
01427 {
01428 if (isalpha((unsigned char) *field[i]))
01429 {
01430 type = DecodeSpecial(i, field[i], &val);
01431 if (type == IGNORE_DTF)
01432 continue;
01433
01434 dmask = DTK_M(type);
01435 switch (type)
01436 {
01437 case MONTH:
01438 tm->tm_mon = val;
01439 break;
01440
01441 case ADBC:
01442 bc = (val == BC);
01443 break;
01444
01445 default:
01446 return -1;
01447 }
01448 if (fmask & dmask)
01449 return -1;
01450
01451 fmask |= dmask;
01452 *tmask |= dmask;
01453
01454
01455 field[i] = NULL;
01456 }
01457 }
01458
01459
01460 for (i = 0; i < nf; i++)
01461 {
01462 if (field[i] == NULL)
01463 continue;
01464
01465 if ((len = strlen(field[i])) <= 0)
01466 return -1;
01467
01468 if (DecodeNumber(len, field[i], fmask, &dmask, tm, &fsec, &is2digits, EuroDates) != 0)
01469 return -1;
01470
01471 if (fmask & dmask)
01472 return -1;
01473
01474 fmask |= dmask;
01475 *tmask |= dmask;
01476 }
01477
01478 if ((fmask & ~(DTK_M(DOY) | DTK_M(TZ))) != DTK_DATE_M)
01479 return -1;
01480
01481
01482 if (bc)
01483 {
01484 if (tm->tm_year > 0)
01485 tm->tm_year = -(tm->tm_year - 1);
01486 else
01487 return -1;
01488 }
01489 else if (is2digits)
01490 {
01491 if (tm->tm_year < 70)
01492 tm->tm_year += 2000;
01493 else if (tm->tm_year < 100)
01494 tm->tm_year += 1900;
01495 }
01496
01497 return 0;
01498 }
01499
01500
01501
01502
01503
01504
01505
01506 int
01507 DecodeTime(char *str, int *tmask, struct tm * tm, fsec_t *fsec)
01508 {
01509 char *cp;
01510
01511 *tmask = DTK_TIME_M;
01512
01513 tm->tm_hour = strtol(str, &cp, 10);
01514 if (*cp != ':')
01515 return -1;
01516 str = cp + 1;
01517 tm->tm_min = strtol(str, &cp, 10);
01518 if (*cp == '\0')
01519 {
01520 tm->tm_sec = 0;
01521 *fsec = 0;
01522 }
01523 else if (*cp != ':')
01524 return -1;
01525 else
01526 {
01527 str = cp + 1;
01528 tm->tm_sec = strtol(str, &cp, 10);
01529 if (*cp == '\0')
01530 *fsec = 0;
01531 else if (*cp == '.')
01532 {
01533 #ifdef HAVE_INT64_TIMESTAMP
01534 char fstr[MAXDATELEN + 1];
01535
01536
01537
01538
01539
01540 strncpy(fstr, (cp + 1), 7);
01541 strcpy(fstr + strlen(fstr), "000000");
01542 *(fstr + 6) = '\0';
01543 *fsec = strtol(fstr, &cp, 10);
01544 #else
01545 str = cp;
01546 *fsec = strtod(str, &cp);
01547 #endif
01548 if (*cp != '\0')
01549 return -1;
01550 }
01551 else
01552 return -1;
01553 }
01554
01555
01556 #ifdef HAVE_INT64_TIMESTAMP
01557 if (tm->tm_hour < 0 || tm->tm_min < 0 || tm->tm_min > 59 ||
01558 tm->tm_sec < 0 || tm->tm_sec > 59 || *fsec >= USECS_PER_SEC)
01559 return -1;
01560 #else
01561 if (tm->tm_hour < 0 || tm->tm_min < 0 || tm->tm_min > 59 ||
01562 tm->tm_sec < 0 || tm->tm_sec > 59 || *fsec >= 1)
01563 return -1;
01564 #endif
01565
01566 return 0;
01567 }
01568
01569
01570
01571
01572
01573
01574
01575 static int
01576 DecodeTimezone(char *str, int *tzp)
01577 {
01578 int tz;
01579 int hr,
01580 min;
01581 char *cp;
01582 int len;
01583
01584
01585 hr = strtol(str + 1, &cp, 10);
01586
01587
01588 if (*cp == ':')
01589 min = strtol(cp + 1, &cp, 10);
01590
01591 else if (*cp == '\0' && (len = strlen(str)) > 3)
01592 {
01593 min = strtol(str + len - 2, &cp, 10);
01594 if (min < 0 || min >= 60)
01595 return -1;
01596
01597 *(str + len - 2) = '\0';
01598 hr = strtol(str + 1, &cp, 10);
01599 if (hr < 0 || hr > 13)
01600 return -1;
01601 }
01602 else
01603 min = 0;
01604
01605 tz = (hr * MINS_PER_HOUR + min) * SECS_PER_MINUTE;
01606 if (*str == '-')
01607 tz = -tz;
01608
01609 *tzp = -tz;
01610 return *cp != '\0';
01611 }
01612
01613
01614
01615
01616
01617
01618
01619
01620 static int
01621 DecodePosixTimezone(char *str, int *tzp)
01622 {
01623 int val,
01624 tz;
01625 int type;
01626 char *cp;
01627 char delim;
01628
01629 cp = str;
01630 while (*cp != '\0' && isalpha((unsigned char) *cp))
01631 cp++;
01632
01633 if (DecodeTimezone(cp, &tz) != 0)
01634 return -1;
01635
01636 delim = *cp;
01637 *cp = '\0';
01638 type = DecodeSpecial(MAXDATEFIELDS - 1, str, &val);
01639 *cp = delim;
01640
01641 switch (type)
01642 {
01643 case DTZ:
01644 case TZ:
01645 *tzp = (val * MINS_PER_HOUR) - tz;
01646 break;
01647
01648 default:
01649 return -1;
01650 }
01651
01652 return 0;
01653 }
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669 int
01670 ParseDateTime(char *timestr, char *lowstr,
01671 char **field, int *ftype, int *numfields, char **endstr)
01672 {
01673 int nf = 0;
01674 char *lp = lowstr;
01675
01676 *endstr = timestr;
01677
01678 while (*(*endstr) != '\0')
01679 {
01680 field[nf] = lp;
01681
01682
01683 if (isdigit((unsigned char) *(*endstr)))
01684 {
01685 *lp++ = *(*endstr)++;
01686 while (isdigit((unsigned char) *(*endstr)))
01687 *lp++ = *(*endstr)++;
01688
01689
01690 if (*(*endstr) == ':')
01691 {
01692 ftype[nf] = DTK_TIME;
01693 *lp++ = *(*endstr)++;
01694 while (isdigit((unsigned char) *(*endstr)) ||
01695 (*(*endstr) == ':') || (*(*endstr) == '.'))
01696 *lp++ = *(*endstr)++;
01697 }
01698
01699 else if (*(*endstr) == '-' || *(*endstr) == '/' || *(*endstr) == '.')
01700 {
01701
01702 char *dp = (*endstr);
01703
01704 *lp++ = *(*endstr)++;
01705
01706 if (isdigit((unsigned char) *(*endstr)))
01707 {
01708 ftype[nf] = (*dp == '.') ? DTK_NUMBER : DTK_DATE;
01709 while (isdigit((unsigned char) *(*endstr)))
01710 *lp++ = *(*endstr)++;
01711
01712
01713
01714
01715
01716 if (*(*endstr) == *dp)
01717 {
01718 ftype[nf] = DTK_DATE;
01719 *lp++ = *(*endstr)++;
01720 while (isdigit((unsigned char) *(*endstr)) || (*(*endstr) == *dp))
01721 *lp++ = *(*endstr)++;
01722 }
01723 }
01724 else
01725 {
01726 ftype[nf] = DTK_DATE;
01727 while (isalnum((unsigned char) *(*endstr)) || (*(*endstr) == *dp))
01728 *lp++ = pg_tolower((unsigned char) *(*endstr)++);
01729 }
01730 }
01731
01732
01733
01734
01735
01736 else
01737 ftype[nf] = DTK_NUMBER;
01738 }
01739
01740 else if (*(*endstr) == '.')
01741 {
01742 *lp++ = *(*endstr)++;
01743 while (isdigit((unsigned char) *(*endstr)))
01744 *lp++ = *(*endstr)++;
01745
01746 ftype[nf] = DTK_NUMBER;
01747 }
01748
01749
01750
01751
01752 else if (isalpha((unsigned char) *(*endstr)))
01753 {
01754 ftype[nf] = DTK_STRING;
01755 *lp++ = pg_tolower((unsigned char) *(*endstr)++);
01756 while (isalpha((unsigned char) *(*endstr)))
01757 *lp++ = pg_tolower((unsigned char) *(*endstr)++);
01758
01759
01760
01761
01762
01763 if (*(*endstr) == '-' || *(*endstr) == '/' || *(*endstr) == '.')
01764 {
01765 char *dp = (*endstr);
01766
01767 ftype[nf] = DTK_DATE;
01768 *lp++ = *(*endstr)++;
01769 while (isdigit((unsigned char) *(*endstr)) || *(*endstr) == *dp)
01770 *lp++ = *(*endstr)++;
01771 }
01772 }
01773
01774 else if (isspace((unsigned char) *(*endstr)))
01775 {
01776 (*endstr)++;
01777 continue;
01778 }
01779
01780 else if (*(*endstr) == '+' || *(*endstr) == '-')
01781 {
01782 *lp++ = *(*endstr)++;
01783
01784 while (isspace((unsigned char) *(*endstr)))
01785 (*endstr)++;
01786
01787 if (isdigit((unsigned char) *(*endstr)))
01788 {
01789 ftype[nf] = DTK_TZ;
01790 *lp++ = *(*endstr)++;
01791 while (isdigit((unsigned char) *(*endstr)) ||
01792 (*(*endstr) == ':') || (*(*endstr) == '.'))
01793 *lp++ = *(*endstr)++;
01794 }
01795
01796 else if (isalpha((unsigned char) *(*endstr)))
01797 {
01798 ftype[nf] = DTK_SPECIAL;
01799 *lp++ = pg_tolower((unsigned char) *(*endstr)++);
01800 while (isalpha((unsigned char) *(*endstr)))
01801 *lp++ = pg_tolower((unsigned char) *(*endstr)++);
01802 }
01803
01804 else
01805 return -1;
01806 }
01807
01808 else if (ispunct((unsigned char) *(*endstr)))
01809 {
01810 (*endstr)++;
01811 continue;
01812
01813 }
01814
01815 else
01816 return -1;
01817
01818
01819 *lp++ = '\0';
01820 nf++;
01821 if (nf > MAXDATEFIELDS)
01822 return -1;
01823 }
01824
01825 *numfields = nf;
01826
01827 return 0;
01828 }
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851 int
01852 DecodeDateTime(char **field, int *ftype, int nf,
01853 int *dtype, struct tm * tm, fsec_t *fsec, bool EuroDates)
01854 {
01855 int fmask = 0,
01856 tmask,
01857 type;
01858 int ptype = 0;
01859 int i;
01860 int val;
01861 int mer = HR24;
01862 int haveTextMonth = FALSE;
01863 int is2digits = FALSE;
01864 int bc = FALSE;
01865 int t = 0;
01866 int *tzp = &t;
01867
01868
01869
01870
01871
01872 *dtype = DTK_DATE;
01873 tm->tm_hour = 0;
01874 tm->tm_min = 0;
01875 tm->tm_sec = 0;
01876 *fsec = 0;
01877
01878 tm->tm_isdst = -1;
01879 if (tzp != NULL)
01880 *tzp = 0;
01881
01882 for (i = 0; i < nf; i++)
01883 {
01884 switch (ftype[i])
01885 {
01886 case DTK_DATE:
01887
01888
01889
01890
01891
01892 if (ptype == DTK_JULIAN)
01893 {
01894 char *cp;
01895 int val;
01896
01897 if (tzp == NULL)
01898 return -1;
01899
01900 val = strtol(field[i], &cp, 10);
01901 if (*cp != '-')
01902 return -1;
01903
01904 j2date(val, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
01905
01906 if (DecodeTimezone(cp, tzp) != 0)
01907 return -1;
01908
01909 tmask = DTK_DATE_M | DTK_TIME_M | DTK_M(TZ);
01910 ptype = 0;
01911 break;
01912 }
01913
01914
01915
01916
01917
01918
01919 else if (((fmask & DTK_DATE_M) == DTK_DATE_M)
01920 || (ptype != 0))
01921 {
01922
01923 if (tzp == NULL)
01924 return -1;
01925
01926 if (isdigit((unsigned char) *field[i]) || ptype != 0)
01927 {
01928 char *cp;
01929
01930 if (ptype != 0)
01931 {
01932
01933 if (ptype != DTK_TIME)
01934 return -1;
01935 ptype = 0;
01936 }
01937
01938
01939
01940
01941
01942
01943 if ((fmask & DTK_TIME_M) == DTK_TIME_M)
01944 return -1;
01945
01946 if ((cp = strchr(field[i], '-')) == NULL)
01947 return -1;
01948
01949
01950 if (DecodeTimezone(cp, tzp) != 0)
01951 return -1;
01952 *cp = '\0';
01953
01954
01955
01956
01957
01958 if ((ftype[i] = DecodeNumberField(strlen(field[i]), field[i], fmask,
01959 &tmask, tm, fsec, &is2digits)) < 0)
01960 return -1;
01961
01962
01963
01964
01965
01966 tmask |= DTK_M(TZ);
01967 }
01968 else
01969 {
01970 if (DecodePosixTimezone(field[i], tzp) != 0)
01971 return -1;
01972
01973 ftype[i] = DTK_TZ;
01974 tmask = DTK_M(TZ);
01975 }
01976 }
01977 else if (DecodeDate(field[i], fmask, &tmask, tm, EuroDates) != 0)
01978 return -1;
01979 break;
01980
01981 case DTK_TIME:
01982 if (DecodeTime(field[i], &tmask, tm, fsec) != 0)
01983 return -1;
01984
01985
01986
01987
01988
01989
01990 if (tm->tm_hour > 24 ||
01991 (tm->tm_hour == 24 && (tm->tm_min > 0 || tm->tm_sec > 0)))
01992 return -1;
01993 break;
01994
01995 case DTK_TZ:
01996 {
01997 int tz;
01998
01999 if (tzp == NULL)
02000 return -1;
02001
02002 if (DecodeTimezone(field[i], &tz) != 0)
02003 return -1;
02004
02005
02006
02007
02008
02009 if (i > 0 && (fmask & DTK_M(TZ)) != 0 &&
02010 ftype[i - 1] == DTK_TZ &&
02011 isalpha((unsigned char) *field[i - 1]))
02012 {
02013 *tzp -= tz;
02014 tmask = 0;
02015 }
02016 else
02017 {
02018 *tzp = tz;
02019 tmask = DTK_M(TZ);
02020 }
02021 }
02022 break;
02023
02024 case DTK_NUMBER:
02025
02026
02027
02028
02029
02030 if (ptype != 0)
02031 {
02032 char *cp;
02033 int val;
02034
02035 val = strtol(field[i], &cp, 10);
02036
02037
02038
02039
02040
02041 if (*cp == '.')
02042 switch (ptype)
02043 {
02044 case DTK_JULIAN:
02045 case DTK_TIME:
02046 case DTK_SECOND:
02047 break;
02048 default:
02049 return 1;
02050 break;
02051 }
02052 else if (*cp != '\0')
02053 return -1;
02054
02055 switch (ptype)
02056 {
02057 case DTK_YEAR:
02058 tm->tm_year = val;
02059 tmask = DTK_M(YEAR);
02060 break;
02061
02062 case DTK_MONTH:
02063
02064
02065
02066
02067
02068 if ((fmask & DTK_M(MONTH)) != 0 &&
02069 (fmask & DTK_M(HOUR)) != 0)
02070 {
02071 tm->tm_min = val;
02072 tmask = DTK_M(MINUTE);
02073 }
02074 else
02075 {
02076 tm->tm_mon = val;
02077 tmask = DTK_M(MONTH);
02078 }
02079 break;
02080
02081 case DTK_DAY:
02082 tm->tm_mday = val;
02083 tmask = DTK_M(DAY);
02084 break;
02085
02086 case DTK_HOUR:
02087 tm->tm_hour = val;
02088 tmask = DTK_M(HOUR);
02089 break;
02090
02091 case DTK_MINUTE:
02092 tm->tm_min = val;
02093 tmask = DTK_M(MINUTE);
02094 break;
02095
02096 case DTK_SECOND:
02097 tm->tm_sec = val;
02098 tmask = DTK_M(SECOND);
02099 if (*cp == '.')
02100 {
02101 double frac;
02102
02103 frac = strtod(cp, &cp);
02104 if (*cp != '\0')
02105 return -1;
02106 #ifdef HAVE_INT64_TIMESTAMP
02107 *fsec = frac * 1000000;
02108 #else
02109 *fsec = frac;
02110 #endif
02111 }
02112 break;
02113
02114 case DTK_TZ:
02115 tmask = DTK_M(TZ);
02116 if (DecodeTimezone(field[i], tzp) != 0)
02117 return -1;
02118 break;
02119
02120 case DTK_JULIAN:
02121
02122
02123
02124 tmask = DTK_DATE_M;
02125 j2date(val, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
02126
02127 if (*cp == '.')
02128 {
02129 double time;
02130
02131 time = strtod(cp, &cp);
02132 if (*cp != '\0')
02133 return -1;
02134
02135 tmask |= DTK_TIME_M;
02136 #ifdef HAVE_INT64_TIMESTAMP
02137 dt2time((time * USECS_PER_DAY), &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
02138 #else
02139 dt2time((time * SECS_PER_DAY), &tm->tm_hour, &tm->tm_min, &tm->tm_sec, fsec);
02140 #endif
02141 }
02142 break;
02143
02144 case DTK_TIME:
02145
02146 if ((ftype[i] = DecodeNumberField(strlen(field[i]), field[i], (fmask | DTK_DATE_M),
02147 &tmask, tm, fsec, &is2digits)) < 0)
02148 return -1;
02149
02150 if (tmask != DTK_TIME_M)
02151 return -1;
02152 break;
02153
02154 default:
02155 return -1;
02156 break;
02157 }
02158
02159 ptype = 0;
02160 *dtype = DTK_DATE;
02161 }
02162 else
02163 {
02164 char *cp;
02165 int flen;
02166
02167 flen = strlen(field[i]);
02168 cp = strchr(field[i], '.');
02169
02170
02171 if (cp != NULL && !(fmask & DTK_DATE_M))
02172 {
02173 if (DecodeDate(field[i], fmask, &tmask, tm, EuroDates) != 0)
02174 return -1;
02175 }
02176
02177 else if (cp != NULL && flen - strlen(cp) > 2)
02178 {
02179
02180
02181
02182
02183
02184 if ((ftype[i] = DecodeNumberField(flen, field[i], fmask,
02185 &tmask, tm, fsec, &is2digits)) < 0)
02186 return -1;
02187 }
02188 else if (flen > 4)
02189 {
02190 if ((ftype[i] = DecodeNumberField(flen, field[i], fmask,
02191 &tmask, tm, fsec, &is2digits)) < 0)
02192 return -1;
02193 }
02194
02195 else if (DecodeNumber(flen, field[i], fmask,
02196 &tmask, tm, fsec, &is2digits, EuroDates) != 0)
02197 return -1;
02198 }
02199 break;
02200
02201 case DTK_STRING:
02202 case DTK_SPECIAL:
02203 type = DecodeSpecial(i, field[i], &val);
02204 if (type == IGNORE_DTF)
02205 continue;
02206
02207 tmask = DTK_M(type);
02208 switch (type)
02209 {
02210 case RESERV:
02211 switch (val)
02212 {
02213 case DTK_NOW:
02214 tmask = (DTK_DATE_M | DTK_TIME_M | DTK_M(TZ));
02215 *dtype = DTK_DATE;
02216 GetCurrentDateTime(tm);
02217 break;
02218
02219 case DTK_YESTERDAY:
02220 tmask = DTK_DATE_M;
02221 *dtype = DTK_DATE;
02222 GetCurrentDateTime(tm);
02223 j2date(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - 1,
02224 &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
02225 tm->tm_hour = 0;
02226 tm->tm_min = 0;
02227 tm->tm_sec = 0;
02228 break;
02229
02230 case DTK_TODAY:
02231 tmask = DTK_DATE_M;
02232 *dtype = DTK_DATE;
02233 GetCurrentDateTime(tm);
02234 tm->tm_hour = 0;
02235 tm->tm_min = 0;
02236 tm->tm_sec = 0;
02237 break;
02238
02239 case DTK_TOMORROW:
02240 tmask = DTK_DATE_M;
02241 *dtype = DTK_DATE;
02242 GetCurrentDateTime(tm);
02243 j2date(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) + 1,
02244 &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
02245 tm->tm_hour = 0;
02246 tm->tm_min = 0;
02247 tm->tm_sec = 0;
02248 break;
02249
02250 case DTK_ZULU:
02251 tmask = (DTK_TIME_M | DTK_M(TZ));
02252 *dtype = DTK_DATE;
02253 tm->tm_hour = 0;
02254 tm->tm_min = 0;
02255 tm->tm_sec = 0;
02256 if (tzp != NULL)
02257 *tzp = 0;
02258 break;
02259
02260 default:
02261 *dtype = val;
02262 }
02263
02264 break;
02265
02266 case MONTH:
02267
02268
02269
02270
02271
02272 if ((fmask & DTK_M(MONTH)) && !haveTextMonth &&
02273 !(fmask & DTK_M(DAY)) && tm->tm_mon >= 1 && tm->tm_mon <= 31)
02274 {
02275 tm->tm_mday = tm->tm_mon;
02276 tmask = DTK_M(DAY);
02277 }
02278 haveTextMonth = TRUE;
02279 tm->tm_mon = val;
02280 break;
02281
02282 case DTZMOD:
02283
02284
02285
02286
02287
02288 tmask |= DTK_M(DTZ);
02289 tm->tm_isdst = 1;
02290 if (tzp == NULL)
02291 return -1;
02292 *tzp += val * MINS_PER_HOUR;
02293 break;
02294
02295 case DTZ:
02296
02297
02298
02299
02300
02301 tmask |= DTK_M(TZ);
02302 tm->tm_isdst = 1;
02303 if (tzp == NULL)
02304 return -1;
02305 *tzp = val * MINS_PER_HOUR;
02306 ftype[i] = DTK_TZ;
02307 break;
02308
02309 case TZ:
02310 tm->tm_isdst = 0;
02311 if (tzp == NULL)
02312 return -1;
02313 *tzp = val * MINS_PER_HOUR;
02314 ftype[i] = DTK_TZ;
02315 break;
02316
02317 case IGNORE_DTF:
02318 break;
02319
02320 case AMPM:
02321 mer = val;
02322 break;
02323
02324 case ADBC:
02325 bc = (val == BC);
02326 break;
02327
02328 case DOW:
02329 tm->tm_wday = val;
02330 break;
02331
02332 case UNITS:
02333 tmask = 0;
02334 ptype = val;
02335 break;
02336
02337 case ISOTIME:
02338
02339
02340
02341
02342
02343 tmask = 0;
02344
02345
02346 if ((fmask & DTK_DATE_M) != DTK_DATE_M)
02347 return -1;
02348
02349
02350
02351
02352
02353
02354
02355 if (i >= nf - 1 ||
02356 (ftype[i + 1] != DTK_NUMBER &&
02357 ftype[i + 1] != DTK_TIME &&
02358 ftype[i + 1] != DTK_DATE))
02359 return -1;
02360
02361 ptype = val;
02362 break;
02363
02364 default:
02365 return -1;
02366 }
02367 break;
02368
02369 default:
02370 return -1;
02371 }
02372
02373 if (tmask & fmask)
02374 return -1;
02375 fmask |= tmask;
02376 }
02377
02378
02379 if (bc)
02380 {
02381 if (tm->tm_year > 0)
02382 tm->tm_year = -(tm->tm_year - 1);
02383 else
02384 return -1;
02385 }
02386 else if (is2digits)
02387 {
02388 if (tm->tm_year < 70)
02389 tm->tm_year += 2000;
02390 else if (tm->tm_year < 100)
02391 tm->tm_year += 1900;
02392 }
02393
02394 if (mer != HR24 && tm->tm_hour > 12)
02395 return -1;
02396 if (mer == AM && tm->tm_hour == 12)
02397 tm->tm_hour = 0;
02398 else if (mer == PM && tm->tm_hour != 12)
02399 tm->tm_hour += 12;
02400
02401
02402 if (*dtype == DTK_DATE)
02403 {
02404 if ((fmask & DTK_DATE_M) != DTK_DATE_M)
02405 return ((fmask & DTK_TIME_M) == DTK_TIME_M) ? 1 : -1;
02406
02407
02408
02409
02410
02411 if (tm->tm_mday < 1 || tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
02412 return -1;
02413
02414
02415
02416
02417
02418
02419 if ((fmask & DTK_DATE_M) == DTK_DATE_M && tzp != NULL && !(fmask & DTK_M(TZ)) && (fmask & DTK_M(DTZMOD)))
02420 return -1;
02421 }
02422
02423 return 0;
02424 }
02425
02426
02427
02428
02429
02430
02431 static char *
02432 find_end_token(char *str, char *fmt)
02433 {
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444
02445
02446
02447
02448
02449 char *end_position = NULL;
02450 char *next_percent,
02451 *subst_location = NULL;
02452 int scan_offset = 0;
02453 char last_char;
02454
02455
02456 if (!*fmt)
02457 {
02458 end_position = fmt;
02459 return end_position;
02460 }
02461
02462
02463 while (fmt[scan_offset] == '%' && fmt[scan_offset + 1])
02464 {
02465
02466
02467
02468
02469
02470
02471 scan_offset += 2;
02472 }
02473 next_percent = strchr(fmt + scan_offset, '%');
02474 if (next_percent)
02475 {
02476
02477
02478
02479
02480
02481
02482
02483 subst_location = next_percent;
02484 while (*(subst_location - 1) == ' ' && subst_location - 1 > fmt + scan_offset)
02485 subst_location--;
02486 last_char = *subst_location;
02487 *subst_location = '\0';
02488
02489
02490
02491
02492
02493
02494
02495
02496
02497
02498
02499
02500
02501 while (*str == ' ')
02502 str++;
02503 end_position = strstr(str, fmt + scan_offset);
02504 *subst_location = last_char;
02505 }
02506 else
02507 {
02508
02509
02510
02511
02512 end_position = str + strlen(str);
02513 }
02514 if (!end_position)
02515 {
02516
02517
02518
02519
02520
02521
02522
02523
02524
02525
02526
02527
02528
02529
02530 if ((fmt + scan_offset)[0] == ' ' && fmt + scan_offset + 1 == subst_location)
02531 end_position = str + strlen(str);
02532 }
02533 return end_position;
02534 }
02535
02536 static int
02537 pgtypes_defmt_scan(union un_fmt_comb * scan_val, int scan_type, char **pstr, char *pfmt)
02538 {
02539
02540
02541
02542
02543
02544 char last_char;
02545 int err = 0;
02546 char *pstr_end;
02547 char *strtol_end = NULL;
02548
02549 while (**pstr == ' ')
02550 pstr++;
02551 pstr_end = find_end_token(*pstr, pfmt);
02552 if (!pstr_end)
02553 {
02554
02555 return 1;
02556 }
02557 last_char = *pstr_end;
02558 *pstr_end = '\0';
02559
02560 switch (scan_type)
02561 {
02562 case PGTYPES_TYPE_UINT:
02563
02564
02565
02566
02567
02568 while (**pstr == ' ')
02569 (*pstr)++;
02570 errno = 0;
02571 scan_val->uint_val = (unsigned int) strtol(*pstr, &strtol_end, 10);
02572 if (errno)
02573 err = 1;
02574 break;
02575 case PGTYPES_TYPE_UINT_LONG:
02576 while (**pstr == ' ')
02577 (*pstr)++;
02578 errno = 0;
02579 scan_val->luint_val = (unsigned long int) strtol(*pstr, &strtol_end, 10);
02580 if (errno)
02581 err = 1;
02582 break;
02583 case PGTYPES_TYPE_STRING_MALLOCED:
02584 scan_val->str_val = pgtypes_strdup(*pstr);
02585 if (scan_val->str_val == NULL)
02586 err = 1;
02587 break;
02588 }
02589 if (strtol_end && *strtol_end)
02590 *pstr = strtol_end;
02591 else
02592 *pstr = pstr_end;
02593 *pstr_end = last_char;
02594 return err;
02595 }
02596
02597
02598 int PGTYPEStimestamp_defmt_scan(char **, char *, timestamp *, int *, int *, int *,
02599 int *, int *, int *, int *);
02600
02601 int
02602 PGTYPEStimestamp_defmt_scan(char **str, char *fmt, timestamp * d,
02603 int *year, int *month, int *day,
02604 int *hour, int *minute, int *second,
02605 int *tz)
02606 {
02607 union un_fmt_comb scan_val;
02608 int scan_type;
02609
02610 char *pstr,
02611 *pfmt,
02612 *tmp;
02613 int err = 1;
02614 unsigned int j;
02615 struct tm tm;
02616
02617 pfmt = fmt;
02618 pstr = *str;
02619
02620 while (*pfmt)
02621 {
02622 err = 0;
02623 while (*pfmt == ' ')
02624 pfmt++;
02625 while (*pstr == ' ')
02626 pstr++;
02627 if (*pfmt != '%')
02628 {
02629 if (*pfmt == *pstr)
02630 {
02631 pfmt++;
02632 pstr++;
02633 }
02634 else
02635 {
02636
02637 err = 1;
02638 return err;
02639 }
02640 continue;
02641 }
02642
02643 pfmt++;
02644 switch (*pfmt)
02645 {
02646 case 'a':
02647 pfmt++;
02648
02649
02650
02651
02652
02653 err = 1;
02654 j = 0;
02655 while (pgtypes_date_weekdays_short[j])
02656 {
02657 if (strncmp(pgtypes_date_weekdays_short[j], pstr,
02658 strlen(pgtypes_date_weekdays_short[j])) == 0)
02659 {
02660
02661 err = 0;
02662 pstr += strlen(pgtypes_date_weekdays_short[j]);
02663 break;
02664 }
02665 j++;
02666 }
02667 break;
02668 case 'A':
02669
02670 pfmt++;
02671 err = 1;
02672 j = 0;
02673 while (days[j])
02674 {
02675 if (strncmp(days[j], pstr, strlen(days[j])) == 0)
02676 {
02677
02678 err = 0;
02679 pstr += strlen(days[j]);
02680 break;
02681 }
02682 j++;
02683 }
02684 break;
02685 case 'b':
02686 case 'h':
02687 pfmt++;
02688 err = 1;
02689 j = 0;
02690 while (months[j])
02691 {
02692 if (strncmp(months[j], pstr, strlen(months[j])) == 0)
02693 {
02694
02695 err = 0;
02696 pstr += strlen(months[j]);
02697 *month = j + 1;
02698 break;
02699 }
02700 j++;
02701 }
02702 break;
02703 case 'B':
02704
02705 pfmt++;
02706 err = 1;
02707 j = 0;
02708 while (pgtypes_date_months[j])
02709 {
02710 if (strncmp(pgtypes_date_months[j], pstr, strlen(pgtypes_date_months[j])) == 0)
02711 {
02712
02713 err = 0;
02714 pstr += strlen(pgtypes_date_months[j]);
02715 *month = j + 1;
02716 break;
02717 }
02718 j++;
02719 }
02720 break;
02721 case 'c':
02722
02723 break;
02724 case 'C':
02725 pfmt++;
02726 scan_type = PGTYPES_TYPE_UINT;
02727 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
02728 *year = scan_val.uint_val * 100;
02729 break;
02730 case 'd':
02731 case 'e':
02732 pfmt++;
02733 scan_type = PGTYPES_TYPE_UINT;
02734 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
02735 *day = scan_val.uint_val;
02736 break;
02737 case 'D':
02738
02739
02740
02741
02742
02743 pfmt++;
02744 tmp = pgtypes_alloc(strlen("%m/%d/%y") + strlen(pstr) + 1);
02745 strcpy(tmp, "%m/%d/%y");
02746 strcat(tmp, pfmt);
02747 err = PGTYPEStimestamp_defmt_scan(&pstr, tmp, d, year, month, day, hour, minute, second, tz);
02748 free(tmp);
02749 return err;
02750 case 'm':
02751 pfmt++;
02752 scan_type = PGTYPES_TYPE_UINT;
02753 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
02754 *month = scan_val.uint_val;
02755 break;
02756 case 'y':
02757 case 'g':
02758 pfmt++;
02759 scan_type = PGTYPES_TYPE_UINT;
02760 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
02761 if (*year < 0)
02762 {
02763
02764 *year = scan_val.uint_val;
02765 }
02766 else
02767 *year += scan_val.uint_val;
02768 if (*year < 100)
02769 *year += 1900;
02770 break;
02771 case 'G':
02772
02773 pfmt++;
02774 scan_type = PGTYPES_TYPE_UINT;
02775 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
02776 *year = scan_val.uint_val;
02777 break;
02778 case 'H':
02779 case 'I':
02780 case 'k':
02781 case 'l':
02782 pfmt++;
02783 scan_type = PGTYPES_TYPE_UINT;
02784 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
02785 *hour += scan_val.uint_val;
02786 break;
02787 case 'j':
02788 pfmt++;
02789 scan_type = PGTYPES_TYPE_UINT;
02790 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
02791
02792
02793
02794
02795
02796
02797 break;
02798 case 'M':
02799 pfmt++;
02800 scan_type = PGTYPES_TYPE_UINT;
02801 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
02802 *minute = scan_val.uint_val;
02803 break;
02804 case 'n':
02805 pfmt++;
02806 if (*pstr == '\n')
02807 pstr++;
02808 else
02809 err = 1;
02810 break;
02811 case 'p':
02812 err = 1;
02813 pfmt++;
02814 if (strncmp(pstr, "am", 2) == 0)
02815 {
02816 *hour += 0;
02817 err = 0;
02818 pstr += 2;
02819 }
02820 if (strncmp(pstr, "a.m.", 4) == 0)
02821 {
02822 *hour += 0;
02823 err = 0;
02824 pstr += 4;
02825 }
02826 if (strncmp(pstr, "pm", 2) == 0)
02827 {
02828 *hour += 12;
02829 err = 0;
02830 pstr += 2;
02831 }
02832 if (strncmp(pstr, "p.m.", 4) == 0)
02833 {
02834 *hour += 12;
02835 err = 0;
02836 pstr += 4;
02837 }
02838 break;
02839 case 'P':
02840 err = 1;
02841 pfmt++;
02842 if (strncmp(pstr, "AM", 2) == 0)
02843 {
02844 *hour += 0;
02845 err = 0;
02846 pstr += 2;
02847 }
02848 if (strncmp(pstr, "A.M.", 4) == 0)
02849 {
02850 *hour += 0;
02851 err = 0;
02852 pstr += 4;
02853 }
02854 if (strncmp(pstr, "PM", 2) == 0)
02855 {
02856 *hour += 12;
02857 err = 0;
02858 pstr += 2;
02859 }
02860 if (strncmp(pstr, "P.M.", 4) == 0)
02861 {
02862 *hour += 12;
02863 err = 0;
02864 pstr += 4;
02865 }
02866 break;
02867 case 'r':
02868 pfmt++;
02869 tmp = pgtypes_alloc(strlen("%I:%M:%S %p") + strlen(pstr) + 1);
02870 strcpy(tmp, "%I:%M:%S %p");
02871 strcat(tmp, pfmt);
02872 err = PGTYPEStimestamp_defmt_scan(&pstr, tmp, d, year, month, day, hour, minute, second, tz);
02873 free(tmp);
02874 return err;
02875 case 'R':
02876 pfmt++;
02877 tmp = pgtypes_alloc(strlen("%H:%M") + strlen(pstr) + 1);
02878 strcpy(tmp, "%H:%M");
02879 strcat(tmp, pfmt);
02880 err = PGTYPEStimestamp_defmt_scan(&pstr, tmp, d, year, month, day, hour, minute, second, tz);
02881 free(tmp);
02882 return err;
02883 case 's':
02884 pfmt++;
02885 scan_type = PGTYPES_TYPE_UINT_LONG;
02886 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
02887
02888 {
02889 struct tm *tms;
02890 time_t et = (time_t) scan_val.luint_val;
02891
02892 tms = gmtime(&et);
02893
02894 if (tms)
02895 {
02896 *year = tms->tm_year + 1900;
02897 *month = tms->tm_mon + 1;
02898 *day = tms->tm_mday;
02899 *hour = tms->tm_hour;
02900 *minute = tms->tm_min;
02901 *second = tms->tm_sec;
02902 }
02903 else
02904 err = 1;
02905 }
02906 break;
02907 case 'S':
02908 pfmt++;
02909 scan_type = PGTYPES_TYPE_UINT;
02910 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
02911 *second = scan_val.uint_val;
02912 break;
02913 case 't':
02914 pfmt++;
02915 if (*pstr == '\t')
02916 pstr++;
02917 else
02918 err = 1;
02919 break;
02920 case 'T':
02921 pfmt++;
02922 tmp = pgtypes_alloc(strlen("%H:%M:%S") + strlen(pstr) + 1);
02923 strcpy(tmp, "%H:%M:%S");
02924 strcat(tmp, pfmt);
02925 err = PGTYPEStimestamp_defmt_scan(&pstr, tmp, d, year, month, day, hour, minute, second, tz);
02926 free(tmp);
02927 return err;
02928 case 'u':
02929 pfmt++;
02930 scan_type = PGTYPES_TYPE_UINT;
02931 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
02932 if (scan_val.uint_val < 1 || scan_val.uint_val > 7)
02933 err = 1;
02934 break;
02935 case 'U':
02936 pfmt++;
02937 scan_type = PGTYPES_TYPE_UINT;
02938 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
02939 if (scan_val.uint_val > 53)
02940 err = 1;
02941 break;
02942 case 'V':
02943 pfmt++;
02944 scan_type = PGTYPES_TYPE_UINT;
02945 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
02946 if (scan_val.uint_val < 1 || scan_val.uint_val > 53)
02947 err = 1;
02948 break;
02949 case 'w':
02950 pfmt++;
02951 scan_type = PGTYPES_TYPE_UINT;
02952 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
02953 if (scan_val.uint_val > 6)
02954 err = 1;
02955 break;
02956 case 'W':
02957 pfmt++;
02958 scan_type = PGTYPES_TYPE_UINT;
02959 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
02960 if (scan_val.uint_val > 53)
02961 err = 1;
02962 break;
02963 case 'x':
02964 case 'X':
02965
02966 break;
02967 case 'Y':
02968 pfmt++;
02969 scan_type = PGTYPES_TYPE_UINT;
02970 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
02971 *year = scan_val.uint_val;
02972 break;
02973 case 'z':
02974 pfmt++;
02975 scan_type = PGTYPES_TYPE_STRING_MALLOCED;
02976 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
02977 if (!err)
02978 {
02979 err = DecodeTimezone(scan_val.str_val, tz);
02980 free(scan_val.str_val);
02981 }
02982 break;
02983 case 'Z':
02984 pfmt++;
02985 scan_type = PGTYPES_TYPE_STRING_MALLOCED;
02986 err = pgtypes_defmt_scan(&scan_val, scan_type, &pstr, pfmt);
02987
02988
02989
02990
02991
02992 for (j = 0; !err && j < szdatetktbl; j++)
02993 {
02994 if (pg_strcasecmp(datetktbl[j].token, scan_val.str_val) == 0)
02995 {
02996
02997
02998
02999
03000
03001 *tz = -15 * MINS_PER_HOUR * datetktbl[j].value;
03002 break;
03003 }
03004 }
03005 free(scan_val.str_val);
03006 break;
03007 case '+':
03008
03009 break;
03010 case '%':
03011 pfmt++;
03012 if (*pstr == '%')
03013 pstr++;
03014 else
03015 err = 1;
03016 break;
03017 default:
03018 err = 1;
03019 }
03020 }
03021 if (!err)
03022 {
03023 if (*second < 0)
03024 *second = 0;
03025 if (*minute < 0)
03026 *minute = 0;
03027 if (*hour < 0)
03028 *hour = 0;
03029 if (*day < 0)
03030 {
03031 err = 1;
03032 *day = 1;
03033 }
03034 if (*month < 0)
03035 {
03036 err = 1;
03037 *month = 1;
03038 }
03039 if (*year < 0)
03040 {
03041 err = 1;
03042 *year = 1970;
03043 }
03044
03045 if (*second > 59)
03046 {
03047 err = 1;
03048 *second = 0;
03049 }
03050 if (*minute > 59)
03051 {
03052 err = 1;
03053 *minute = 0;
03054 }
03055 if (*hour > 24 ||
03056 (*hour == 24 && (*minute > 0 || *second > 0)))
03057 {
03058 err = 1;
03059 *hour = 0;
03060 }
03061 if (*month > MONTHS_PER_YEAR)
03062 {
03063 err = 1;
03064 *month = 1;
03065 }
03066 if (*day > day_tab[isleap(*year)][*month - 1])
03067 {
03068 *day = day_tab[isleap(*year)][*month - 1];
03069 err = 1;
03070 }
03071
03072 tm.tm_sec = *second;
03073 tm.tm_min = *minute;
03074 tm.tm_hour = *hour;
03075 tm.tm_mday = *day;
03076 tm.tm_mon = *month;
03077 tm.tm_year = *year;
03078
03079 tm2timestamp(&tm, 0, tz, d);
03080 }
03081 return err;
03082 }
03083
03084