Skip to content

Commit 094ec2d

Browse files
committed
More timezone patches by Thomas:
Here are patches which should help fix timezone problems in the datetime and abstime code. Also, I repatched varlena.c to add in some comments and a little error checking on top of Vadim's earlier repairs. There are slight mods to the circle data type to have the distance operator between circles measure the distance between closest points rather than between centers.
1 parent b8e376c commit 094ec2d

File tree

8 files changed

+252
-222
lines changed

8 files changed

+252
-222
lines changed

src/backend/utils/adt/dt.c

Lines changed: 160 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.16 1997/04/22 17:36:44 scrappy Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.17 1997/04/25 18:40:13 scrappy Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -120,6 +120,7 @@ char *
120120
datetime_out(DateTime *dt)
121121
{
122122
char *result;
123+
int tz;
123124
struct tm tt, *tm = &tt;
124125
double fsec;
125126
char buf[MAXDATELEN+1];
@@ -130,8 +131,8 @@ datetime_out(DateTime *dt)
130131
if (DATETIME_IS_RESERVED(*dt)) {
131132
EncodeSpecialDateTime(*dt, buf);
132133

133-
} else if (datetime2tm( *dt, &CTimeZone, tm, &fsec) == 0) {
134-
EncodeDateTime(tm, fsec, DateStyle, buf);
134+
} else if (datetime2tm( *dt, &tz, tm, &fsec) == 0) {
135+
EncodeDateTime(tm, fsec, &tz, DateStyle, buf);
135136

136137
} else {
137138
EncodeSpecialDateTime(DT_INVALID, buf);
@@ -840,6 +841,7 @@ datetime_part(text *units, DateTime *datetime)
840841
float64 result;
841842

842843
DateTime dt;
844+
int tz;
843845
int type, val;
844846
int i;
845847
char *up, *lp, lowunits[MAXDATELEN+1];
@@ -874,10 +876,10 @@ printf( "datetime_part- units %s type=%d value=%d\n", lowunits, type, val);
874876

875877
dt = (DATETIME_IS_RELATIVE(*datetime)? SetDateTime(*datetime): *datetime);
876878

877-
if (datetime2tm( dt, &CTimeZone, tm, &fsec) == 0) {
879+
if (datetime2tm( dt, &tz, tm, &fsec) == 0) {
878880
switch (val) {
879881
case DTK_TZ:
880-
*result = CTimeZone;
882+
*result = tz;
881883
break;
882884

883885
case DTK_MICROSEC:
@@ -929,7 +931,7 @@ printf( "datetime_part- units %s type=%d value=%d\n", lowunits, type, val);
929931
break;
930932

931933
default:
932-
elog(WARN,"Datetime units %s not yet supported",units);
934+
elog(WARN,"Datetime units %s not supported",units);
933935
*result = 0;
934936
};
935937

@@ -1401,21 +1403,9 @@ datetime2tm( DateTime dt, int *tzp, struct tm *tm, double *fsec)
14011403
{
14021404
double date, time, sec;
14031405
time_t utime;
1404-
1405-
if (tzp != NULL) {
1406-
/* XXX HACK to get time behavior compatible with Postgres v6.0 - tgl 97/04/07 */
1407-
if ((tm->tm_year > 1902) && (tm->tm_year < 2038)) {
1408-
utime = ((date2j(2000,1,1)-date2j(1970,1,1))*86400+dt);
1409-
localtime((time_t *) &utime);
1410-
#ifdef DATEDEBUG
1411-
printf( "datetime2tm- use system time zone = %ld (CTimeZone = %d)\n", (long int) utime, CTimeZone);
1406+
#ifdef USE_POSIX_TIME
1407+
struct tm *tx;
14121408
#endif
1413-
dt = dt2local( dt, timezone);
1414-
1415-
} else {
1416-
dt = dt2local( dt, *tzp);
1417-
};
1418-
};
14191409

14201410
time = (modf( dt/86400, &date)*86400);
14211411
date += date2j(2000,1,1);
@@ -1428,16 +1418,15 @@ printf( "datetime2tm- use system time zone = %ld (CTimeZone = %d)\n", (long int)
14281418
if (date < 0) return -1;
14291419

14301420
#ifdef DATEDEBUG
1431-
printf( "datetime2tm- date is %f (%f %f)\n",
1432-
((tzp != NULL)? dt2local(dt, -(*tzp)): dt), date, time);
1421+
printf( "datetime2tm- date is %f (%f %f)\n", dt, date, time);
14331422
#endif
14341423

14351424
j2date((int) date, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
14361425
dt2time( time, &tm->tm_hour, &tm->tm_min, &sec);
14371426

14381427
#ifdef DATEDEBUG
14391428
printf( "datetime2tm- date is %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, tm->tm_mday);
1440-
printf( "datetime2tm- time is %02d:%02d:%2.2f\n", tm->tm_hour, tm->tm_min, sec);
1429+
printf( "datetime2tm- time is %02d:%02d:%02.0f\n", tm->tm_hour, tm->tm_min, sec);
14411430
#endif
14421431

14431432
*fsec = modf(JROUND(sec),&sec);
@@ -1447,11 +1436,62 @@ printf( "datetime2tm- time is %02d:%02d:%2.2f\n", tm->tm_hour, tm->tm_min, sec);
14471436
printf( "datetime2tm- time is %02d:%02d:%02d %.7f\n", tm->tm_hour, tm->tm_min, tm->tm_sec, *fsec);
14481437
#endif
14491438

1450-
tm->tm_isdst = -1;
1439+
if (tzp != NULL) {
1440+
/* XXX HACK to get time behavior compatible with Postgres v6.0 - tgl 97/04/07 */
1441+
if ((tm->tm_year >= 1902) && (tm->tm_year < 2038)) {
1442+
utime = (dt + (date2j(2000,1,1)-date2j(1970,1,1))*86400);
1443+
#ifdef USE_POSIX_TIME
1444+
tx = localtime(&utime);
1445+
#ifdef DATEDEBUG
1446+
printf( "datetime2tm- (localtime) %d.%02d.%02d %02d:%02d:%02.0f %s %s dst=%d\n",
1447+
tx->tm_year, tx->tm_mon, tx->tm_mday, tx->tm_hour, tx->tm_min, sec,
1448+
tzname[0], tzname[1], tx->tm_isdst);
1449+
#endif
1450+
tm->tm_year = tx->tm_year + 1900;
1451+
tm->tm_mon = tx->tm_mon + 1;
1452+
tm->tm_mday = tx->tm_mday;
1453+
tm->tm_hour = tx->tm_hour;
1454+
tm->tm_min = tx->tm_min;
1455+
tm->tm_sec = tx->tm_sec;
1456+
tm->tm_isdst = tx->tm_isdst;
1457+
#ifdef HAVE_INT_TIMEZONE
1458+
*tzp = (tm->tm_isdst? (timezone - 3600): timezone);
1459+
#else /* !HAVE_INT_TIMEZONE */
1460+
*tzp = (tm->tm_isdst? (tm->tm_gmtoff - 3600): tm->tm_gmtoff); /* tm_gmtoff is Sun/DEC-ism */
1461+
#endif
1462+
#else /* !USE_POSIX_TIME */
1463+
*tzp = CTimeZone; /* V7 conventions; don't know timezone? */
1464+
#endif
1465+
} else {
1466+
*tzp = 0;
1467+
tm->tm_isdst = 0;
1468+
#ifdef USE_POSIX_TIME
1469+
#ifdef HAVE_INT_TIMEZONE
1470+
tzname[0] = "GMT";
1471+
#else /* !HAVE_INT_TIMEZONE */
1472+
tm->tm_zone = "GMT";
1473+
#endif
1474+
#else /* !USE_POSIX_TIME */
1475+
strcpy( CTZName, "GMT");
1476+
#endif
1477+
};
1478+
1479+
dt = dt2local( dt, *tzp);
1480+
1481+
} else {
1482+
tm->tm_isdst = 0;
1483+
};
1484+
1485+
#ifdef DATEDEBUG
1486+
printf( "datetime2tm- date is %d.%02d.%02d\n", tm->tm_year, tm->tm_mon, tm->tm_mday);
1487+
printf( "datetime2tm- time is %02d:%02d:%02d %.7f\n", tm->tm_hour, tm->tm_min, tm->tm_sec, *fsec);
1488+
#endif
14511489

14521490
#ifdef DATEDEBUG
1491+
#ifdef HAVE_INT_TIMEZONE
14531492
printf( "datetime2tm- timezone is %s; offset is %d (%d); daylight is %d\n",
1454-
CTZName, ((tzp != NULL)? *tzp: 0), CTimeZone, CDayLight);
1493+
tzname[tm->tm_isdst != 0], ((tzp != NULL)? *tzp: 0), CTimeZone, CDayLight);
1494+
#endif
14551495
#endif
14561496

14571497
return 0;
@@ -1824,9 +1864,13 @@ printf( "DecodeDateTime- month field %s value is %d\n", field[i], val);
18241864
break;
18251865

18261866
case DTZ:
1827-
tm->tm_isdst = 0;
1828-
/* FALLTHROUGH! */
1867+
tm->tm_isdst = 1;
1868+
if (tzp == NULL) return -1;
1869+
*tzp = val * 60;
1870+
break;
1871+
18291872
case TZ:
1873+
tm->tm_isdst = 0;
18301874
if (tzp == NULL) return -1;
18311875
*tzp = val * 60;
18321876
break;
@@ -1883,15 +1927,29 @@ printf( " %02d:%02d:%02d\n", tm->tm_hour, tm->tm_min, tm->tm_sec);
18831927
/* timezone not specified? then find local timezone if possible */
18841928
/* XXX HACK to get correct behavior relative to Postgres v6.0 - tgl 97/04/07 */
18851929
if ((*dtype == DTK_DATE) && ((fmask & DTK_DATE_M) == DTK_DATE_M)
1886-
&& (tzp != NULL) && (! (fmask & DTK_M(TZ)))
1887-
&& (tm->tm_year > 1902) && (tm->tm_year < 2038)) {
1888-
tm->tm_year -= 1900;
1889-
tm->tm_mon -= 1;
1890-
mktime(tm);
1891-
tm->tm_year += 1900;
1892-
tm->tm_mon += 1;
1930+
&& (tzp != NULL) && (! (fmask & DTK_M(TZ)))) {
1931+
1932+
if ((tm->tm_year >= 1902) && (tm->tm_year < 2038)) {
1933+
#ifdef USE_POSIX_TIME
1934+
tm->tm_year -= 1900;
1935+
tm->tm_mon -= 1;
1936+
tm->tm_isdst = -1;
1937+
mktime(tm);
1938+
tm->tm_year += 1900;
1939+
tm->tm_mon += 1;
18931940

1894-
*tzp = timezone;
1941+
#ifdef HAVE_INT_TIMEZONE
1942+
*tzp = ((tm->tm_isdst > 0)? (timezone - 3600): timezone);
1943+
#else /* !HAVE_INT_TIMEZONE */
1944+
*tzp = tm->tm_gmtoff;
1945+
#endif
1946+
#else /* !USE_POSIX_TIME */
1947+
*tzp = CTimeZone;
1948+
#endif
1949+
} else {
1950+
tm->tm_isdst = 0;
1951+
*tzp = 0;
1952+
};
18951953
};
18961954

18971955
return 0;
@@ -1960,7 +2018,7 @@ printf( "DecodeTimeOnly- RESERV field %s value is %d\n", field[i], val);
19602018
tm->tm_hour = 0;
19612019
tm->tm_min = 0;
19622020
tm->tm_sec = 0;
1963-
tm->tm_isdst = -1;
2021+
tm->tm_isdst = 0;
19642022
break;
19652023

19662024
default:
@@ -2695,7 +2753,7 @@ printf( "EncodeSpecialDateTime- unrecognized date\n");
26952753
/* EncodeDateTime()
26962754
* Encode date and time interpreted as local time.
26972755
*/
2698-
int EncodeDateTime(struct tm *tm, double fsec, int style, char *str)
2756+
int EncodeDateTime(struct tm *tm, double fsec, int *tzp, int style, char *str)
26992757
{
27002758
char mabbrev[4], dabbrev[4];
27012759
int day, hour, min;
@@ -2706,11 +2764,36 @@ int EncodeDateTime(struct tm *tm, double fsec, int style, char *str)
27062764

27072765
sec = (tm->tm_sec + fsec);
27082766

2767+
#if FALSE
27092768
tm->tm_isdst = -1;
2769+
#endif
27102770

27112771
#ifdef DATEDEBUG
2772+
#ifdef USE_POSIX_TIME
2773+
#ifdef HAVE_INT_TIMEZONE
2774+
printf( "EncodeDateTime- timezone is %s (%s); offset is %d (%d); daylight is %d (%d)\n",
2775+
tzname[0], CTZName, *tzp, CTimeZone, tm->tm_isdst, CDayLight);
2776+
#else
27122777
printf( "EncodeDateTime- timezone is %s (%s); offset is %ld (%d); daylight is %d (%d)\n",
2713-
tzname[0], CTZName, (long int) timezone, CTimeZone, daylight, CDayLight);
2778+
tm->tm_zone, CTZName, (- tm->tm_gmtoff), CTimeZone, tm->tm_isdst, CDayLight);
2779+
#endif
2780+
#else
2781+
printf( "EncodeDateTime- timezone is %s; offset is %d; daylight is %d\n",
2782+
CTZName, CTimeZone, CDayLight);
2783+
#endif
2784+
#endif
2785+
2786+
#ifdef USE_POSIX_TIME
2787+
/* XXX HACK to get time behavior compatible with Postgres v6.0 - tgl 97/04/07 */
2788+
if ((tm->tm_year >= 1902) && (tm->tm_year < 2038)) {
2789+
tm->tm_year -= 1900;
2790+
tm->tm_mon -= 1;
2791+
mktime(tm);
2792+
tm->tm_year += 1900;
2793+
tm->tm_mon += 1;
2794+
} else {
2795+
tm->tm_isdst = -1;
2796+
};
27142797
#endif
27152798

27162799
day = date2j( tm->tm_year, tm->tm_mon, tm->tm_mday);
@@ -2730,21 +2813,20 @@ printf( "EncodeDateTime- day is %d\n", day);
27302813
/* compatible with ISO date formats */
27312814
if (style == USE_ISO_DATES) {
27322815
if (tm->tm_year > 0) {
2733-
#if FALSE
2734-
sprintf( str, "%04d-%02d-%02d %02d:%02d:%05.2f %s",
2735-
tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, sec, CTZName);
2736-
#endif
27372816
sprintf( str, "%04d-%02d-%02d %02d:%02d:",
27382817
tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min);
27392818
sprintf( (str+17), ((fsec != 0)? "%05.2f": "%02.0f"), sec);
2740-
hour = -(CTimeZone / 3600);
2741-
min = ((abs(CTimeZone) / 60) % 60);
2742-
sprintf( (str+strlen(str)), ((min != 0)? "%+03d:%02d": "%+03d"), hour, min);
2743-
#if FALSE
2744-
sprintf( str, "%04d-%02d-%02d %02d:%02d:%05.2f%+03d:%02d",
2745-
tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, sec,
2746-
hour, min);
2747-
#endif
2819+
2820+
if (tm->tm_isdst >= 0) {
2821+
if (tzp != NULL) {
2822+
hour = -(*tzp / 3600);
2823+
min = ((abs(*tzp) / 60) % 60);
2824+
} else {
2825+
hour = 0;
2826+
min = 0;
2827+
};
2828+
sprintf( (str+strlen(str)), ((min != 0)? "%+03d:%02d": "%+03d"), hour, min);
2829+
};
27482830

27492831
} else {
27502832
if (tm->tm_hour || tm->tm_min) {
@@ -2764,8 +2846,20 @@ printf( "EncodeDateTime- day is %d\n", day);
27642846
sprintf( str, "%02d/%02d", tm->tm_mon, tm->tm_mday);
27652847
};
27662848
if (tm->tm_year > 0) {
2767-
sprintf( (str+5), "/%04d %02d:%02d:%05.2f %s",
2768-
tm->tm_year, tm->tm_hour, tm->tm_min, sec, CTZName);
2849+
sprintf( (str+5), "/%04d %02d:%02d:%05.2f",
2850+
tm->tm_year, tm->tm_hour, tm->tm_min, sec);
2851+
2852+
if (tm->tm_isdst >= 0) {
2853+
#ifdef USE_POSIX_TIME
2854+
#ifdef HAVE_INT_TIMEZONE
2855+
sprintf( (str+22), " %s", tzname[(tm->tm_isdst > 0)]);
2856+
#else /* !HAVE_INT_TIMEZONE */
2857+
sprintf( (str+22), " %s", tm->tm_zone);
2858+
#endif
2859+
#else /* !USE_POSIX_TIME */
2860+
sprintf( (str+22), " %s", CTZName);
2861+
#endif
2862+
};
27692863

27702864
} else {
27712865
sprintf( (str+5), "/%04d %02d:%02d %s",
@@ -2781,12 +2875,20 @@ printf( "EncodeDateTime- day is %d\n", day);
27812875
sprintf( (str+4), "%3s %02d", mabbrev, tm->tm_mday);
27822876
};
27832877
if (tm->tm_year > 0) {
2784-
#if FALSE
2785-
sprintf( (str+10), " %02d:%02d:%05.2f %04d %s",
2786-
tm->tm_hour, tm->tm_min, sec, tm->tm_year, CTZName);
2878+
sprintf( (str+10), " %02d:%02d:%05.2f %04d",
2879+
tm->tm_hour, tm->tm_min, sec, tm->tm_year);
2880+
2881+
if (tm->tm_isdst >= 0) {
2882+
#ifdef USE_POSIX_TIME
2883+
#ifdef HAVE_INT_TIMEZONE
2884+
sprintf( (str+27), " %s", tzname[(tm->tm_isdst > 0)]);
2885+
#else
2886+
sprintf( (str+27), " %s", tm->tm_zone);
27872887
#endif
2788-
sprintf( (str+10), " %02d:%02d:%05.2f %04d %s",
2789-
tm->tm_hour, tm->tm_min, sec, tm->tm_year, (daylight? tzname[1]: tzname[0]));
2888+
#else
2889+
sprintf( (str+27), " %s", CTZName);
2890+
#endif
2891+
};
27902892

27912893
} else {
27922894
sprintf( (str+10), " %02d:%02d %04d %s",
@@ -2798,7 +2900,7 @@ printf( "EncodeDateTime- day is %d\n", day);
27982900
printf( "EncodeDateTime- date result is %s\n", str);
27992901
#endif
28002902

2801-
#ifdef DATEDEBUG
2903+
#if defined(DATEDEBUG) && FALSE
28022904
if (tm->tm_year >= 1000) tm->tm_year -= 1900;
28032905
tm->tm_mon -= 1;
28042906
strftime( buf, sizeof(buf), "%y.%m.%d %H:%M:%S %Z", tm);

0 commit comments

Comments
 (0)