00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "c.h"
00016
00017 #include <fcntl.h>
00018
00019 #include "datatype/timestamp.h"
00020 #include "private.h"
00021 #include "pgtz.h"
00022 #include "tzfile.h"
00023
00024
00025 #ifndef WILDABBR
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #define WILDABBR " "
00047 #endif
00048
00049 static char wildabbr[] = WILDABBR;
00050
00051 static const char gmt[] = "GMT";
00052
00053
00054
00055
00056
00057
00058
00059
00060 #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
00061
00062 struct rule
00063 {
00064 int r_type;
00065 int r_day;
00066 int r_week;
00067 int r_mon;
00068 long r_time;
00069 };
00070
00071 #define JULIAN_DAY 0
00072 #define DAY_OF_YEAR 1
00073 #define MONTH_NTH_DAY_OF_WEEK 2
00074
00075
00076
00077
00078
00079 static long detzcode(const char *codep);
00080 static pg_time_t detzcode64(const char *codep);
00081 static int differ_by_repeat(pg_time_t t1, pg_time_t t0);
00082 static const char *getzname(const char *strp);
00083 static const char *getqzname(const char *strp, int delim);
00084 static const char *getnum(const char *strp, int *nump, int min, int max);
00085 static const char *getsecs(const char *strp, long *secsp);
00086 static const char *getoffset(const char *strp, long *offsetp);
00087 static const char *getrule(const char *strp, struct rule * rulep);
00088 static void gmtload(struct state * sp);
00089 static struct pg_tm *gmtsub(const pg_time_t *timep, long offset,
00090 struct pg_tm * tmp);
00091 static struct pg_tm *localsub(const pg_time_t *timep, long offset,
00092 struct pg_tm * tmp, const pg_tz *tz);
00093 static int increment_overflow(int *number, int delta);
00094 static pg_time_t transtime(pg_time_t janfirst, int year,
00095 const struct rule * rulep, long offset);
00096 static int typesequiv(const struct state * sp, int a, int b);
00097 static struct pg_tm *timesub(const pg_time_t *timep, long offset,
00098 const struct state * sp, struct pg_tm * tmp);
00099
00100
00101 static struct state gmtmem;
00102
00103 #define gmtptr (&gmtmem)
00104
00105
00106 static int gmt_is_set = 0;
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116 static struct pg_tm tm;
00117
00118
00119 static long
00120 detzcode(const char *codep)
00121 {
00122 long result;
00123 int i;
00124
00125 result = (codep[0] & 0x80) ? ~0L : 0;
00126 for (i = 0; i < 4; ++i)
00127 result = (result << 8) | (codep[i] & 0xff);
00128 return result;
00129 }
00130
00131 static pg_time_t
00132 detzcode64(const char *codep)
00133 {
00134 pg_time_t result;
00135 int i;
00136
00137 result = (codep[0] & 0x80) ? (~(int64) 0) : 0;
00138 for (i = 0; i < 8; ++i)
00139 result = result * 256 + (codep[i] & 0xff);
00140 return result;
00141 }
00142
00143 static int
00144 differ_by_repeat(pg_time_t t1, pg_time_t t0)
00145 {
00146 if (TYPE_INTEGRAL(pg_time_t) &&
00147 TYPE_BIT(pg_time_t) -TYPE_SIGNED(pg_time_t) <SECSPERREPEAT_BITS)
00148 return 0;
00149 return t1 - t0 == SECSPERREPEAT;
00150 }
00151
00152 int
00153 tzload(const char *name, char *canonname, struct state * sp, int doextend)
00154 {
00155 const char *p;
00156 int i;
00157 int fid;
00158 int stored;
00159 int nread;
00160 union
00161 {
00162 struct tzhead tzhead;
00163 char buf[2 * sizeof(struct tzhead) +
00164 2 * sizeof *sp +
00165 4 * TZ_MAX_TIMES];
00166 } u;
00167
00168 sp->goback = sp->goahead = FALSE;
00169 if (name == NULL && (name = TZDEFAULT) == NULL)
00170 return -1;
00171 if (name[0] == ':')
00172 ++name;
00173 fid = pg_open_tzfile(name, canonname);
00174 if (fid < 0)
00175 return -1;
00176 nread = read(fid, u.buf, sizeof u.buf);
00177 if (close(fid) != 0 || nread <= 0)
00178 return -1;
00179 for (stored = 4; stored <= 8; stored *= 2)
00180 {
00181 int ttisstdcnt;
00182 int ttisgmtcnt;
00183
00184 ttisstdcnt = (int) detzcode(u.tzhead.tzh_ttisstdcnt);
00185 ttisgmtcnt = (int) detzcode(u.tzhead.tzh_ttisgmtcnt);
00186 sp->leapcnt = (int) detzcode(u.tzhead.tzh_leapcnt);
00187 sp->timecnt = (int) detzcode(u.tzhead.tzh_timecnt);
00188 sp->typecnt = (int) detzcode(u.tzhead.tzh_typecnt);
00189 sp->charcnt = (int) detzcode(u.tzhead.tzh_charcnt);
00190 p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
00191 if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
00192 sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
00193 sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
00194 sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
00195 (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
00196 (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
00197 return -1;
00198 if (nread - (p - u.buf) <
00199 sp->timecnt * stored +
00200 sp->timecnt +
00201 sp->typecnt * 6 +
00202 sp->charcnt +
00203 sp->leapcnt * (stored + 4) +
00204 ttisstdcnt +
00205 ttisgmtcnt)
00206 return -1;
00207 for (i = 0; i < sp->timecnt; ++i)
00208 {
00209 sp->ats[i] = (stored == 4) ? detzcode(p) : detzcode64(p);
00210 p += stored;
00211 }
00212 for (i = 0; i < sp->timecnt; ++i)
00213 {
00214 sp->types[i] = (unsigned char) *p++;
00215 if (sp->types[i] >= sp->typecnt)
00216 return -1;
00217 }
00218 for (i = 0; i < sp->typecnt; ++i)
00219 {
00220 struct ttinfo *ttisp;
00221
00222 ttisp = &sp->ttis[i];
00223 ttisp->tt_gmtoff = detzcode(p);
00224 p += 4;
00225 ttisp->tt_isdst = (unsigned char) *p++;
00226 if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
00227 return -1;
00228 ttisp->tt_abbrind = (unsigned char) *p++;
00229 if (ttisp->tt_abbrind < 0 ||
00230 ttisp->tt_abbrind > sp->charcnt)
00231 return -1;
00232 }
00233 for (i = 0; i < sp->charcnt; ++i)
00234 sp->chars[i] = *p++;
00235 sp->chars[i] = '\0';
00236 for (i = 0; i < sp->leapcnt; ++i)
00237 {
00238 struct lsinfo *lsisp;
00239
00240 lsisp = &sp->lsis[i];
00241 lsisp->ls_trans = (stored == 4) ? detzcode(p) : detzcode64(p);
00242 p += stored;
00243 lsisp->ls_corr = detzcode(p);
00244 p += 4;
00245 }
00246 for (i = 0; i < sp->typecnt; ++i)
00247 {
00248 struct ttinfo *ttisp;
00249
00250 ttisp = &sp->ttis[i];
00251 if (ttisstdcnt == 0)
00252 ttisp->tt_ttisstd = FALSE;
00253 else
00254 {
00255 ttisp->tt_ttisstd = *p++;
00256 if (ttisp->tt_ttisstd != TRUE &&
00257 ttisp->tt_ttisstd != FALSE)
00258 return -1;
00259 }
00260 }
00261 for (i = 0; i < sp->typecnt; ++i)
00262 {
00263 struct ttinfo *ttisp;
00264
00265 ttisp = &sp->ttis[i];
00266 if (ttisgmtcnt == 0)
00267 ttisp->tt_ttisgmt = FALSE;
00268 else
00269 {
00270 ttisp->tt_ttisgmt = *p++;
00271 if (ttisp->tt_ttisgmt != TRUE &&
00272 ttisp->tt_ttisgmt != FALSE)
00273 return -1;
00274 }
00275 }
00276
00277
00278
00279
00280
00281 for (i = 0; i < sp->timecnt - 2; ++i)
00282 if (sp->ats[i] > sp->ats[i + 1])
00283 {
00284 ++i;
00285 if (TYPE_SIGNED(pg_time_t))
00286 {
00287
00288
00289
00290 sp->timecnt = i;
00291 }
00292 else
00293 {
00294
00295
00296
00297 int j;
00298
00299 for (j = 0; j + i < sp->timecnt; ++j)
00300 {
00301 sp->ats[j] = sp->ats[j + i];
00302 sp->types[j] = sp->types[j + i];
00303 }
00304 sp->timecnt = j;
00305 }
00306 break;
00307 }
00308
00309
00310
00311
00312 if (u.tzhead.tzh_version[0] == '\0')
00313 break;
00314 nread -= p - u.buf;
00315 for (i = 0; i < nread; ++i)
00316 u.buf[i] = p[i];
00317
00318
00319
00320
00321 if (stored >= (int) sizeof(pg_time_t) && TYPE_INTEGRAL(pg_time_t))
00322 break;
00323 }
00324 if (doextend && nread > 2 &&
00325 u.buf[0] == '\n' && u.buf[nread - 1] == '\n' &&
00326 sp->typecnt + 2 <= TZ_MAX_TYPES)
00327 {
00328 struct state ts;
00329 int result;
00330
00331 u.buf[nread - 1] = '\0';
00332 result = tzparse(&u.buf[1], &ts, FALSE);
00333 if (result == 0 && ts.typecnt == 2 &&
00334 sp->charcnt + ts.charcnt <= TZ_MAX_CHARS)
00335 {
00336 for (i = 0; i < 2; ++i)
00337 ts.ttis[i].tt_abbrind +=
00338 sp->charcnt;
00339 for (i = 0; i < ts.charcnt; ++i)
00340 sp->chars[sp->charcnt++] =
00341 ts.chars[i];
00342 i = 0;
00343 while (i < ts.timecnt &&
00344 ts.ats[i] <=
00345 sp->ats[sp->timecnt - 1])
00346 ++i;
00347 while (i < ts.timecnt &&
00348 sp->timecnt < TZ_MAX_TIMES)
00349 {
00350 sp->ats[sp->timecnt] =
00351 ts.ats[i];
00352 sp->types[sp->timecnt] =
00353 sp->typecnt +
00354 ts.types[i];
00355 ++sp->timecnt;
00356 ++i;
00357 }
00358 sp->ttis[sp->typecnt++] = ts.ttis[0];
00359 sp->ttis[sp->typecnt++] = ts.ttis[1];
00360 }
00361 }
00362 if (sp->timecnt > 1)
00363 {
00364 for (i = 1; i < sp->timecnt; ++i)
00365 if (typesequiv(sp, sp->types[i], sp->types[0]) &&
00366 differ_by_repeat(sp->ats[i], sp->ats[0]))
00367 {
00368 sp->goback = TRUE;
00369 break;
00370 }
00371 for (i = sp->timecnt - 2; i >= 0; --i)
00372 if (typesequiv(sp, sp->types[sp->timecnt - 1],
00373 sp->types[i]) &&
00374 differ_by_repeat(sp->ats[sp->timecnt - 1],
00375 sp->ats[i]))
00376 {
00377 sp->goahead = TRUE;
00378 break;
00379 }
00380 }
00381 return 0;
00382 }
00383
00384 static int
00385 typesequiv(const struct state * sp, int a, int b)
00386 {
00387 int result;
00388
00389 if (sp == NULL ||
00390 a < 0 || a >= sp->typecnt ||
00391 b < 0 || b >= sp->typecnt)
00392 result = FALSE;
00393 else
00394 {
00395 const struct ttinfo *ap = &sp->ttis[a];
00396 const struct ttinfo *bp = &sp->ttis[b];
00397
00398 result = ap->tt_gmtoff == bp->tt_gmtoff &&
00399 ap->tt_isdst == bp->tt_isdst &&
00400 ap->tt_ttisstd == bp->tt_ttisstd &&
00401 ap->tt_ttisgmt == bp->tt_ttisgmt &&
00402 strcmp(&sp->chars[ap->tt_abbrind],
00403 &sp->chars[bp->tt_abbrind]) == 0;
00404 }
00405 return result;
00406 }
00407
00408 static const int mon_lengths[2][MONSPERYEAR] = {
00409 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
00410 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
00411 };
00412
00413 static const int year_lengths[2] = {
00414 DAYSPERNYEAR, DAYSPERLYEAR
00415 };
00416
00417
00418
00419
00420
00421
00422 static const char *
00423 getzname(const char *strp)
00424 {
00425 char c;
00426
00427 while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
00428 c != '+')
00429 ++strp;
00430 return strp;
00431 }
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441 static const char *
00442 getqzname(const char *strp, int delim)
00443 {
00444 int c;
00445
00446 while ((c = *strp) != '\0' && c != delim)
00447 ++strp;
00448 return strp;
00449 }
00450
00451
00452
00453
00454
00455
00456
00457 static const char *
00458 getnum(const char *strp, int *nump, int min, int max)
00459 {
00460 char c;
00461 int num;
00462
00463 if (strp == NULL || !is_digit(c = *strp))
00464 return NULL;
00465 num = 0;
00466 do
00467 {
00468 num = num * 10 + (c - '0');
00469 if (num > max)
00470 return NULL;
00471 c = *++strp;
00472 } while (is_digit(c));
00473 if (num < min)
00474 return NULL;
00475 *nump = num;
00476 return strp;
00477 }
00478
00479
00480
00481
00482
00483
00484
00485
00486 static const char *
00487 getsecs(const char *strp, long *secsp)
00488 {
00489 int num;
00490
00491
00492
00493
00494
00495
00496 strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
00497 if (strp == NULL)
00498 return NULL;
00499 *secsp = num * (long) SECSPERHOUR;
00500 if (*strp == ':')
00501 {
00502 ++strp;
00503 strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
00504 if (strp == NULL)
00505 return NULL;
00506 *secsp += num * SECSPERMIN;
00507 if (*strp == ':')
00508 {
00509 ++strp;
00510
00511 strp = getnum(strp, &num, 0, SECSPERMIN);
00512 if (strp == NULL)
00513 return NULL;
00514 *secsp += num;
00515 }
00516 }
00517 return strp;
00518 }
00519
00520
00521
00522
00523
00524
00525
00526 static const char *
00527 getoffset(const char *strp, long *offsetp)
00528 {
00529 int neg = 0;
00530
00531 if (*strp == '-')
00532 {
00533 neg = 1;
00534 ++strp;
00535 }
00536 else if (*strp == '+')
00537 ++strp;
00538 strp = getsecs(strp, offsetp);
00539 if (strp == NULL)
00540 return NULL;
00541 if (neg)
00542 *offsetp = -*offsetp;
00543 return strp;
00544 }
00545
00546
00547
00548
00549
00550
00551
00552 static const char *
00553 getrule(const char *strp, struct rule * rulep)
00554 {
00555 if (*strp == 'J')
00556 {
00557
00558
00559
00560 rulep->r_type = JULIAN_DAY;
00561 ++strp;
00562 strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
00563 }
00564 else if (*strp == 'M')
00565 {
00566
00567
00568
00569 rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
00570 ++strp;
00571 strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
00572 if (strp == NULL)
00573 return NULL;
00574 if (*strp++ != '.')
00575 return NULL;
00576 strp = getnum(strp, &rulep->r_week, 1, 5);
00577 if (strp == NULL)
00578 return NULL;
00579 if (*strp++ != '.')
00580 return NULL;
00581 strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
00582 }
00583 else if (is_digit(*strp))
00584 {
00585
00586
00587
00588 rulep->r_type = DAY_OF_YEAR;
00589 strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
00590 }
00591 else
00592 return NULL;
00593 if (strp == NULL)
00594 return NULL;
00595 if (*strp == '/')
00596 {
00597
00598
00599
00600 ++strp;
00601 strp = getsecs(strp, &rulep->r_time);
00602 }
00603 else
00604 rulep->r_time = 2 * SECSPERHOUR;
00605 return strp;
00606 }
00607
00608
00609
00610
00611
00612
00613 static pg_time_t
00614 transtime(pg_time_t janfirst, int year,
00615 const struct rule * rulep, long offset)
00616 {
00617 int leapyear;
00618 pg_time_t value = 0;
00619 int i,
00620 d,
00621 m1,
00622 yy0,
00623 yy1,
00624 yy2,
00625 dow;
00626
00627 leapyear = isleap(year);
00628 switch (rulep->r_type)
00629 {
00630
00631 case JULIAN_DAY:
00632
00633
00634
00635
00636
00637
00638
00639 value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
00640 if (leapyear && rulep->r_day >= 60)
00641 value += SECSPERDAY;
00642 break;
00643
00644 case DAY_OF_YEAR:
00645
00646
00647
00648
00649
00650 value = janfirst + rulep->r_day * SECSPERDAY;
00651 break;
00652
00653 case MONTH_NTH_DAY_OF_WEEK:
00654
00655
00656
00657
00658 value = janfirst;
00659 for (i = 0; i < rulep->r_mon - 1; ++i)
00660 value += mon_lengths[leapyear][i] * SECSPERDAY;
00661
00662
00663
00664
00665
00666 m1 = (rulep->r_mon + 9) % 12 + 1;
00667 yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
00668 yy1 = yy0 / 100;
00669 yy2 = yy0 % 100;
00670 dow = ((26 * m1 - 2) / 10 +
00671 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
00672 if (dow < 0)
00673 dow += DAYSPERWEEK;
00674
00675
00676
00677
00678
00679 d = rulep->r_day - dow;
00680 if (d < 0)
00681 d += DAYSPERWEEK;
00682 for (i = 1; i < rulep->r_week; ++i)
00683 {
00684 if (d + DAYSPERWEEK >=
00685 mon_lengths[leapyear][rulep->r_mon - 1])
00686 break;
00687 d += DAYSPERWEEK;
00688 }
00689
00690
00691
00692
00693 value += d * SECSPERDAY;
00694 break;
00695 }
00696
00697
00698
00699
00700
00701
00702 return value + rulep->r_time + offset;
00703 }
00704
00705
00706
00707
00708
00709
00710 int
00711 tzparse(const char *name, struct state * sp, int lastditch)
00712 {
00713 const char *stdname;
00714 const char *dstname = NULL;
00715 size_t stdlen;
00716 size_t dstlen;
00717 long stdoffset;
00718 long dstoffset;
00719 pg_time_t *atp;
00720 unsigned char *typep;
00721 char *cp;
00722 int load_result;
00723
00724 stdname = name;
00725 if (lastditch)
00726 {
00727 stdlen = strlen(name);
00728 name += stdlen;
00729 if (stdlen >= sizeof sp->chars)
00730 stdlen = (sizeof sp->chars) - 1;
00731 stdoffset = 0;
00732
00733
00734
00735
00736
00737
00738 sp->goback = sp->goahead = FALSE;
00739 load_result = -1;
00740 }
00741 else
00742 {
00743 if (*name == '<')
00744 {
00745 name++;
00746 stdname = name;
00747 name = getqzname(name, '>');
00748 if (*name != '>')
00749 return (-1);
00750 stdlen = name - stdname;
00751 name++;
00752 }
00753 else
00754 {
00755 name = getzname(name);
00756 stdlen = name - stdname;
00757 }
00758 if (*name == '\0')
00759 return -1;
00760 name = getoffset(name, &stdoffset);
00761 if (name == NULL)
00762 return -1;
00763 load_result = tzload(TZDEFRULES, NULL, sp, FALSE);
00764 }
00765 if (load_result != 0)
00766 sp->leapcnt = 0;
00767 if (*name != '\0')
00768 {
00769 if (*name == '<')
00770 {
00771 dstname = ++name;
00772 name = getqzname(name, '>');
00773 if (*name != '>')
00774 return -1;
00775 dstlen = name - dstname;
00776 name++;
00777 }
00778 else
00779 {
00780 dstname = name;
00781 name = getzname(name);
00782 dstlen = name - dstname;
00783 }
00784 if (*name != '\0' && *name != ',' && *name != ';')
00785 {
00786 name = getoffset(name, &dstoffset);
00787 if (name == NULL)
00788 return -1;
00789 }
00790 else
00791 dstoffset = stdoffset - SECSPERHOUR;
00792 if (*name == '\0' && load_result != 0)
00793 name = TZDEFRULESTRING;
00794 if (*name == ',' || *name == ';')
00795 {
00796 struct rule start;
00797 struct rule end;
00798 int year;
00799 pg_time_t janfirst;
00800 pg_time_t starttime;
00801 pg_time_t endtime;
00802
00803 ++name;
00804 if ((name = getrule(name, &start)) == NULL)
00805 return -1;
00806 if (*name++ != ',')
00807 return -1;
00808 if ((name = getrule(name, &end)) == NULL)
00809 return -1;
00810 if (*name != '\0')
00811 return -1;
00812 sp->typecnt = 2;
00813
00814
00815
00816
00817 sp->ttis[0].tt_gmtoff = -dstoffset;
00818 sp->ttis[0].tt_isdst = 1;
00819 sp->ttis[0].tt_abbrind = stdlen + 1;
00820 sp->ttis[1].tt_gmtoff = -stdoffset;
00821 sp->ttis[1].tt_isdst = 0;
00822 sp->ttis[1].tt_abbrind = 0;
00823 atp = sp->ats;
00824 typep = sp->types;
00825 janfirst = 0;
00826 sp->timecnt = 0;
00827 for (year = EPOCH_YEAR;
00828 sp->timecnt + 2 <= TZ_MAX_TIMES;
00829 ++year)
00830 {
00831 pg_time_t newfirst;
00832
00833 starttime = transtime(janfirst, year, &start,
00834 stdoffset);
00835 endtime = transtime(janfirst, year, &end,
00836 dstoffset);
00837 if (starttime > endtime)
00838 {
00839 *atp++ = endtime;
00840 *typep++ = 1;
00841 *atp++ = starttime;
00842 *typep++ = 0;
00843 }
00844 else
00845 {
00846 *atp++ = starttime;
00847 *typep++ = 0;
00848 *atp++ = endtime;
00849 *typep++ = 1;
00850 }
00851 sp->timecnt += 2;
00852 newfirst = janfirst;
00853 newfirst += year_lengths[isleap(year)] *
00854 SECSPERDAY;
00855 if (newfirst <= janfirst)
00856 break;
00857 janfirst = newfirst;
00858 }
00859 }
00860 else
00861 {
00862 long theirstdoffset;
00863 long theirdstoffset;
00864 long theiroffset;
00865 int isdst;
00866 int i;
00867 int j;
00868
00869 if (*name != '\0')
00870 return -1;
00871
00872
00873
00874
00875 theirstdoffset = 0;
00876 for (i = 0; i < sp->timecnt; ++i)
00877 {
00878 j = sp->types[i];
00879 if (!sp->ttis[j].tt_isdst)
00880 {
00881 theirstdoffset =
00882 -sp->ttis[j].tt_gmtoff;
00883 break;
00884 }
00885 }
00886 theirdstoffset = 0;
00887 for (i = 0; i < sp->timecnt; ++i)
00888 {
00889 j = sp->types[i];
00890 if (sp->ttis[j].tt_isdst)
00891 {
00892 theirdstoffset =
00893 -sp->ttis[j].tt_gmtoff;
00894 break;
00895 }
00896 }
00897
00898
00899
00900
00901 isdst = FALSE;
00902 theiroffset = theirstdoffset;
00903
00904
00905
00906
00907
00908 for (i = 0; i < sp->timecnt; ++i)
00909 {
00910 j = sp->types[i];
00911 sp->types[i] = sp->ttis[j].tt_isdst;
00912 if (sp->ttis[j].tt_ttisgmt)
00913 {
00914
00915 }
00916 else
00917 {
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929 if (isdst && !sp->ttis[j].tt_ttisstd)
00930 {
00931 sp->ats[i] += dstoffset -
00932 theirdstoffset;
00933 }
00934 else
00935 {
00936 sp->ats[i] += stdoffset -
00937 theirstdoffset;
00938 }
00939 }
00940 theiroffset = -sp->ttis[j].tt_gmtoff;
00941 if (sp->ttis[j].tt_isdst)
00942 theirdstoffset = theiroffset;
00943 else
00944 theirstdoffset = theiroffset;
00945 }
00946
00947
00948
00949
00950 sp->ttis[0].tt_gmtoff = -stdoffset;
00951 sp->ttis[0].tt_isdst = FALSE;
00952 sp->ttis[0].tt_abbrind = 0;
00953 sp->ttis[1].tt_gmtoff = -dstoffset;
00954 sp->ttis[1].tt_isdst = TRUE;
00955 sp->ttis[1].tt_abbrind = stdlen + 1;
00956 sp->typecnt = 2;
00957 }
00958 }
00959 else
00960 {
00961 dstlen = 0;
00962 sp->typecnt = 1;
00963 sp->timecnt = 0;
00964 sp->ttis[0].tt_gmtoff = -stdoffset;
00965 sp->ttis[0].tt_isdst = 0;
00966 sp->ttis[0].tt_abbrind = 0;
00967 }
00968 sp->charcnt = stdlen + 1;
00969 if (dstlen != 0)
00970 sp->charcnt += dstlen + 1;
00971 if ((size_t) sp->charcnt > sizeof sp->chars)
00972 return -1;
00973 cp = sp->chars;
00974 (void) strncpy(cp, stdname, stdlen);
00975 cp += stdlen;
00976 *cp++ = '\0';
00977 if (dstlen != 0)
00978 {
00979 (void) strncpy(cp, dstname, dstlen);
00980 *(cp + dstlen) = '\0';
00981 }
00982 return 0;
00983 }
00984
00985 static void
00986 gmtload(struct state * sp)
00987 {
00988 if (tzload(gmt, NULL, sp, TRUE) != 0)
00989 (void) tzparse(gmt, sp, TRUE);
00990 }
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001 static struct pg_tm *
01002 localsub(const pg_time_t *timep, long offset,
01003 struct pg_tm * tmp, const pg_tz *tz)
01004 {
01005 const struct state *sp;
01006 const struct ttinfo *ttisp;
01007 int i;
01008 struct pg_tm *result;
01009 const pg_time_t t = *timep;
01010
01011 sp = &tz->state;
01012 if ((sp->goback && t < sp->ats[0]) ||
01013 (sp->goahead && t > sp->ats[sp->timecnt - 1]))
01014 {
01015 pg_time_t newt = t;
01016 pg_time_t seconds;
01017 pg_time_t tcycles;
01018 int64 icycles;
01019
01020 if (t < sp->ats[0])
01021 seconds = sp->ats[0] - t;
01022 else
01023 seconds = t - sp->ats[sp->timecnt - 1];
01024 --seconds;
01025 tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
01026 ++tcycles;
01027 icycles = tcycles;
01028 if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
01029 return NULL;
01030 seconds = icycles;
01031 seconds *= YEARSPERREPEAT;
01032 seconds *= AVGSECSPERYEAR;
01033 if (t < sp->ats[0])
01034 newt += seconds;
01035 else
01036 newt -= seconds;
01037 if (newt < sp->ats[0] ||
01038 newt > sp->ats[sp->timecnt - 1])
01039 return NULL;
01040 result = localsub(&newt, offset, tmp, tz);
01041 if (result == tmp)
01042 {
01043 pg_time_t newy;
01044
01045 newy = tmp->tm_year;
01046 if (t < sp->ats[0])
01047 newy -= icycles * YEARSPERREPEAT;
01048 else
01049 newy += icycles * YEARSPERREPEAT;
01050 tmp->tm_year = newy;
01051 if (tmp->tm_year != newy)
01052 return NULL;
01053 }
01054 return result;
01055 }
01056 if (sp->timecnt == 0 || t < sp->ats[0])
01057 {
01058 i = 0;
01059 while (sp->ttis[i].tt_isdst)
01060 if (++i >= sp->typecnt)
01061 {
01062 i = 0;
01063 break;
01064 }
01065 }
01066 else
01067 {
01068 int lo = 1;
01069 int hi = sp->timecnt;
01070
01071 while (lo < hi)
01072 {
01073 int mid = (lo + hi) >> 1;
01074
01075 if (t < sp->ats[mid])
01076 hi = mid;
01077 else
01078 lo = mid + 1;
01079 }
01080 i = (int) sp->types[lo - 1];
01081 }
01082 ttisp = &sp->ttis[i];
01083
01084 result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
01085 tmp->tm_isdst = ttisp->tt_isdst;
01086 tmp->tm_zone = &sp->chars[ttisp->tt_abbrind];
01087 return result;
01088 }
01089
01090
01091 struct pg_tm *
01092 pg_localtime(const pg_time_t *timep, const pg_tz *tz)
01093 {
01094 return localsub(timep, 0L, &tm, tz);
01095 }
01096
01097
01098
01099
01100
01101 static struct pg_tm *
01102 gmtsub(const pg_time_t *timep, long offset, struct pg_tm * tmp)
01103 {
01104 struct pg_tm *result;
01105
01106 if (!gmt_is_set)
01107 {
01108 gmt_is_set = TRUE;
01109 gmtload(gmtptr);
01110 }
01111 result = timesub(timep, offset, gmtptr, tmp);
01112
01113
01114
01115
01116
01117
01118 if (offset != 0)
01119 tmp->tm_zone = wildabbr;
01120 else
01121 tmp->tm_zone = gmtptr->chars;
01122
01123 return result;
01124 }
01125
01126 struct pg_tm *
01127 pg_gmtime(const pg_time_t *timep)
01128 {
01129 return gmtsub(timep, 0L, &tm);
01130 }
01131
01132
01133
01134
01135
01136 static int
01137 leaps_thru_end_of(const int y)
01138 {
01139 return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
01140 -(leaps_thru_end_of(-(y + 1)) + 1);
01141 }
01142
01143
01144 static struct pg_tm *
01145 timesub(const pg_time_t *timep, long offset,
01146 const struct state * sp, struct pg_tm * tmp)
01147 {
01148 const struct lsinfo *lp;
01149 pg_time_t tdays;
01150 int idays;
01151 long rem;
01152 int y;
01153 const int *ip;
01154 long corr;
01155 int hit;
01156 int i;
01157
01158 corr = 0;
01159 hit = 0;
01160 i = sp->leapcnt;
01161 while (--i >= 0)
01162 {
01163 lp = &sp->lsis[i];
01164 if (*timep >= lp->ls_trans)
01165 {
01166 if (*timep == lp->ls_trans)
01167 {
01168 hit = ((i == 0 && lp->ls_corr > 0) ||
01169 lp->ls_corr > sp->lsis[i - 1].ls_corr);
01170 if (hit)
01171 while (i > 0 &&
01172 sp->lsis[i].ls_trans ==
01173 sp->lsis[i - 1].ls_trans + 1 &&
01174 sp->lsis[i].ls_corr ==
01175 sp->lsis[i - 1].ls_corr + 1)
01176 {
01177 ++hit;
01178 --i;
01179 }
01180 }
01181 corr = lp->ls_corr;
01182 break;
01183 }
01184 }
01185 y = EPOCH_YEAR;
01186 tdays = *timep / SECSPERDAY;
01187 rem = *timep - tdays * SECSPERDAY;
01188 while (tdays < 0 || tdays >= year_lengths[isleap(y)])
01189 {
01190 int newy;
01191 pg_time_t tdelta;
01192 int idelta;
01193 int leapdays;
01194
01195 tdelta = tdays / DAYSPERLYEAR;
01196 idelta = tdelta;
01197 if (tdelta - idelta >= 1 || idelta - tdelta >= 1)
01198 return NULL;
01199 if (idelta == 0)
01200 idelta = (tdays < 0) ? -1 : 1;
01201 newy = y;
01202 if (increment_overflow(&newy, idelta))
01203 return NULL;
01204 leapdays = leaps_thru_end_of(newy - 1) -
01205 leaps_thru_end_of(y - 1);
01206 tdays -= ((pg_time_t) newy - y) * DAYSPERNYEAR;
01207 tdays -= leapdays;
01208 y = newy;
01209 }
01210 {
01211 long seconds;
01212
01213 seconds = tdays * SECSPERDAY + 0.5;
01214 tdays = seconds / SECSPERDAY;
01215 rem += seconds - tdays * SECSPERDAY;
01216 }
01217
01218
01219
01220
01221 idays = tdays;
01222 rem += offset - corr;
01223 while (rem < 0)
01224 {
01225 rem += SECSPERDAY;
01226 --idays;
01227 }
01228 while (rem >= SECSPERDAY)
01229 {
01230 rem -= SECSPERDAY;
01231 ++idays;
01232 }
01233 while (idays < 0)
01234 {
01235 if (increment_overflow(&y, -1))
01236 return NULL;
01237 idays += year_lengths[isleap(y)];
01238 }
01239 while (idays >= year_lengths[isleap(y)])
01240 {
01241 idays -= year_lengths[isleap(y)];
01242 if (increment_overflow(&y, 1))
01243 return NULL;
01244 }
01245 tmp->tm_year = y;
01246 if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
01247 return NULL;
01248 tmp->tm_yday = idays;
01249
01250
01251
01252
01253 tmp->tm_wday = EPOCH_WDAY +
01254 ((y - EPOCH_YEAR) % DAYSPERWEEK) *
01255 (DAYSPERNYEAR % DAYSPERWEEK) +
01256 leaps_thru_end_of(y - 1) -
01257 leaps_thru_end_of(EPOCH_YEAR - 1) +
01258 idays;
01259 tmp->tm_wday %= DAYSPERWEEK;
01260 if (tmp->tm_wday < 0)
01261 tmp->tm_wday += DAYSPERWEEK;
01262 tmp->tm_hour = (int) (rem / SECSPERHOUR);
01263 rem %= SECSPERHOUR;
01264 tmp->tm_min = (int) (rem / SECSPERMIN);
01265
01266
01267
01268
01269
01270 tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
01271 ip = mon_lengths[isleap(y)];
01272 for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
01273 idays -= ip[tmp->tm_mon];
01274 tmp->tm_mday = (int) (idays + 1);
01275 tmp->tm_isdst = 0;
01276 tmp->tm_gmtoff = offset;
01277 return tmp;
01278 }
01279
01280
01281
01282
01283
01284 static int
01285 increment_overflow(int *number, int delta)
01286 {
01287 int number0;
01288
01289 number0 = *number;
01290 *number += delta;
01291 return (*number < number0) != (delta < 0);
01292 }
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314 int
01315 pg_next_dst_boundary(const pg_time_t *timep,
01316 long int *before_gmtoff,
01317 int *before_isdst,
01318 pg_time_t *boundary,
01319 long int *after_gmtoff,
01320 int *after_isdst,
01321 const pg_tz *tz)
01322 {
01323 const struct state *sp;
01324 const struct ttinfo *ttisp;
01325 int i;
01326 int j;
01327 const pg_time_t t = *timep;
01328
01329 sp = &tz->state;
01330 if (sp->timecnt == 0)
01331 {
01332
01333 i = 0;
01334 while (sp->ttis[i].tt_isdst)
01335 if (++i >= sp->typecnt)
01336 {
01337 i = 0;
01338 break;
01339 }
01340 ttisp = &sp->ttis[i];
01341 *before_gmtoff = ttisp->tt_gmtoff;
01342 *before_isdst = ttisp->tt_isdst;
01343 return 0;
01344 }
01345 if ((sp->goback && t < sp->ats[0]) ||
01346 (sp->goahead && t > sp->ats[sp->timecnt - 1]))
01347 {
01348
01349 pg_time_t newt = t;
01350 pg_time_t seconds;
01351 pg_time_t tcycles;
01352 int64 icycles;
01353 int result;
01354
01355 if (t < sp->ats[0])
01356 seconds = sp->ats[0] - t;
01357 else
01358 seconds = t - sp->ats[sp->timecnt - 1];
01359 --seconds;
01360 tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
01361 ++tcycles;
01362 icycles = tcycles;
01363 if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
01364 return -1;
01365 seconds = icycles;
01366 seconds *= YEARSPERREPEAT;
01367 seconds *= AVGSECSPERYEAR;
01368 if (t < sp->ats[0])
01369 newt += seconds;
01370 else
01371 newt -= seconds;
01372 if (newt < sp->ats[0] ||
01373 newt > sp->ats[sp->timecnt - 1])
01374 return -1;
01375
01376 result = pg_next_dst_boundary(&newt, before_gmtoff,
01377 before_isdst,
01378 boundary,
01379 after_gmtoff,
01380 after_isdst,
01381 tz);
01382 if (t < sp->ats[0])
01383 *boundary -= seconds;
01384 else
01385 *boundary += seconds;
01386 return result;
01387 }
01388
01389 if (t >= sp->ats[sp->timecnt - 1])
01390 {
01391
01392 i = sp->types[sp->timecnt - 1];
01393 ttisp = &sp->ttis[i];
01394 *before_gmtoff = ttisp->tt_gmtoff;
01395 *before_isdst = ttisp->tt_isdst;
01396 return 0;
01397 }
01398 if (t < sp->ats[0])
01399 {
01400
01401 i = 0;
01402 while (sp->ttis[i].tt_isdst)
01403 if (++i >= sp->typecnt)
01404 {
01405 i = 0;
01406 break;
01407 }
01408 ttisp = &sp->ttis[i];
01409 *before_gmtoff = ttisp->tt_gmtoff;
01410 *before_isdst = ttisp->tt_isdst;
01411 *boundary = sp->ats[0];
01412
01413 i = sp->types[0];
01414 ttisp = &sp->ttis[i];
01415 *after_gmtoff = ttisp->tt_gmtoff;
01416 *after_isdst = ttisp->tt_isdst;
01417 return 1;
01418 }
01419
01420 {
01421 int lo = 1;
01422 int hi = sp->timecnt - 1;
01423
01424 while (lo < hi)
01425 {
01426 int mid = (lo + hi) >> 1;
01427
01428 if (t < sp->ats[mid])
01429 hi = mid;
01430 else
01431 lo = mid + 1;
01432 }
01433 i = lo;
01434 }
01435 j = sp->types[i - 1];
01436 ttisp = &sp->ttis[j];
01437 *before_gmtoff = ttisp->tt_gmtoff;
01438 *before_isdst = ttisp->tt_isdst;
01439 *boundary = sp->ats[i];
01440 j = sp->types[i];
01441 ttisp = &sp->ttis[j];
01442 *after_gmtoff = ttisp->tt_gmtoff;
01443 *after_isdst = ttisp->tt_isdst;
01444 return 1;
01445 }
01446
01447
01448
01449
01450
01451 bool
01452 pg_get_timezone_offset(const pg_tz *tz, long int *gmtoff)
01453 {
01454
01455
01456
01457
01458
01459 const struct state *sp;
01460 int i;
01461
01462 sp = &tz->state;
01463 for (i = 1; i < sp->typecnt; i++)
01464 {
01465 if (sp->ttis[i].tt_gmtoff != sp->ttis[0].tt_gmtoff)
01466 return false;
01467 }
01468 *gmtoff = sp->ttis[0].tt_gmtoff;
01469 return true;
01470 }
01471
01472
01473
01474
01475 const char *
01476 pg_get_timezone_name(pg_tz *tz)
01477 {
01478 if (tz)
01479 return tz->TZname;
01480 return NULL;
01481 }
01482
01483
01484
01485
01486
01487
01488
01489
01490 bool
01491 pg_tz_acceptable(pg_tz *tz)
01492 {
01493 struct pg_tm *tt;
01494 pg_time_t time2000;
01495
01496
01497
01498
01499
01500
01501 time2000 = (POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY;
01502 tt = pg_localtime(&time2000, tz);
01503 if (!tt || tt->tm_sec != 0)
01504 return false;
01505
01506 return true;
01507 }