Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf5ba72e

Browse files
committed
Consolidate several near-identical uses of mktime() into a single
routine DetermineLocalTimeZone(). In that routine, be more wary ofbroken mktime() implementations than the original code was: don't allowmktime to change the already-set y/m/d/h/m/s information, and don'tuse tm_gmtoff if mktime failed. Possibly this will resolve some ofthe complaints we've been hearing from users of Middle Eastern timezoneson RedHat.
1 parent0cec2bb commitf5ba72e

File tree

4 files changed

+69
-122
lines changed

4 files changed

+69
-122
lines changed

‎src/backend/utils/adt/datetime.c

Lines changed: 61 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.63 2001/04/0318:05:53 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.64 2001/05/0322:53:07 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -869,37 +869,75 @@ DecodeDateTime(char **field, int *ftype, int nf,
869869
if (fmask&DTK_M(DTZMOD))
870870
return-1;
871871

872-
if (IS_VALID_UTIME(tm->tm_year,tm->tm_mon,tm->tm_mday))
873-
{
872+
*tzp=DetermineLocalTimeZone(tm);
873+
}
874+
}
875+
876+
return0;
877+
}/* DecodeDateTime() */
878+
879+
880+
/* DetermineLocalTimeZone()
881+
* Given a struct tm in which tm_year, tm_mon, tm_mday, tm_hour, tm_min, and
882+
* tm_sec fields are set, attempt to determine the applicable local zone
883+
* (ie, regular or daylight-savings time) at that time. Set the struct tm's
884+
* tm_isdst field accordingly, and return the actual timezone offset.
885+
*
886+
* This subroutine exists mainly to centralize uses of mktime() and defend
887+
* against mktime() bugs on various platforms...
888+
*/
889+
int
890+
DetermineLocalTimeZone(structtm*tm)
891+
{
892+
inttz;
893+
894+
if (IS_VALID_UTIME(tm->tm_year,tm->tm_mon,tm->tm_mday))
895+
{
874896
#if defined(HAVE_TM_ZONE)|| defined(HAVE_INT_TIMEZONE)
875-
tm->tm_year-=1900;
876-
tm->tm_mon-=1;
877-
tm->tm_isdst=-1;
878-
mktime(tm);
879-
tm->tm_year+=1900;
880-
tm->tm_mon+=1;
897+
/*
898+
* Some buggy mktime() implementations may change the year/month/day
899+
* when given a time right at a DST boundary. To prevent corruption
900+
* of the caller's data, give mktime() a copy...
901+
*/
902+
structtmtt,
903+
*tmp=&tt;
904+
905+
*tmp=*tm;
906+
/* change to Unix conventions for year/month */
907+
tmp->tm_year-=1900;
908+
tmp->tm_mon-=1;
909+
910+
/* indicate timezone unknown */
911+
tmp->tm_isdst=-1;
912+
913+
mktime(tmp);
914+
915+
tm->tm_isdst=tmp->tm_isdst;
881916

882917
#if defined(HAVE_TM_ZONE)
883-
*tzp=-(tm->tm_gmtoff);/* tm_gmtoff is
884-
* Sun/DEC-ism */
918+
/* tm_gmtoff is Sun/DEC-ism */
919+
if (tmp->tm_isdst >=0)
920+
tz=-(tmp->tm_gmtoff);
921+
else
922+
tz=0;/* assume GMT if mktime failed */
885923
#elif defined(HAVE_INT_TIMEZONE)
886-
*tzp= ((tm->tm_isdst>0) ? (TIMEZONE_GLOBAL-3600) :TIMEZONE_GLOBAL);
924+
tz= ((tmp->tm_isdst>0) ? (TIMEZONE_GLOBAL-3600) :TIMEZONE_GLOBAL);
887925
#endif/* HAVE_INT_TIMEZONE */
888926

889927
#else/* not (HAVE_TM_ZONE || HAVE_INT_TIMEZONE) */
890-
*tzp=CTimeZone;
928+
tm->tm_isdst=0;
929+
tz=CTimeZone;
891930
#endif
892-
}
893-
else
894-
{
895-
tm->tm_isdst=0;
896-
*tzp=0;
897-
}
898-
}
931+
}
932+
else
933+
{
934+
/* Given date is out of range, so assume GMT */
935+
tm->tm_isdst=0;
936+
tz=0;
899937
}
900938

901-
return0;
902-
}/* DecodeDateTime() */
939+
returntz;
940+
}
903941

904942

905943
/* DecodeTimeOnly()
@@ -1119,22 +1157,8 @@ DecodeTimeOnly(char **field, int *ftype, int nf,
11191157
tmp->tm_min=tm->tm_min;
11201158
tmp->tm_sec=tm->tm_sec;
11211159

1122-
#if defined(HAVE_TM_ZONE)|| defined(HAVE_INT_TIMEZONE)
1123-
tmp->tm_year-=1900;
1124-
tmp->tm_mon-=1;
1125-
tmp->tm_isdst=-1;
1126-
mktime(tmp);
1160+
*tzp=DetermineLocalTimeZone(tmp);
11271161
tm->tm_isdst=tmp->tm_isdst;
1128-
1129-
#if defined(HAVE_TM_ZONE)
1130-
*tzp=-(tmp->tm_gmtoff);/* tm_gmtoff is Sun/DEC-ism */
1131-
#elif defined(HAVE_INT_TIMEZONE)
1132-
*tzp= ((tmp->tm_isdst>0) ? (TIMEZONE_GLOBAL-3600) :TIMEZONE_GLOBAL);
1133-
#endif
1134-
1135-
#else/* not (HAVE_TM_ZONE || HAVE_INT_TIMEZONE) */
1136-
*tzp=CTimeZone;
1137-
#endif
11381162
}
11391163

11401164
return0;

‎src/backend/utils/adt/formatting.c

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* -----------------------------------------------------------------------
22
* formatting.c
33
*
4-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.36 2001/03/23 04:49:54 momjian Exp $
4+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.37 2001/05/03 22:53:07 tgl Exp $
55
*
66
*
77
* Portions Copyright (c) 1999-2000, PostgreSQL Global Development Group
@@ -2936,37 +2936,7 @@ to_timestamp(PG_FUNCTION_ARGS)
29362936
#ifdefDEBUG_TO_FROM_CHAR
29372937
NOTICE_TM;
29382938
#endif
2939-
if (IS_VALID_UTIME(tm->tm_year,tm->tm_mon,tm->tm_mday))
2940-
{
2941-
2942-
#if defined(HAVE_TM_ZONE)|| defined(HAVE_INT_TIMEZONE)
2943-
tm->tm_isdst=-1;
2944-
tm->tm_year-=1900;
2945-
tm->tm_mon-=1;
2946-
2947-
#ifdefDEBUG_TO_FROM_CHAR
2948-
elog(DEBUG_elog_output,"TO-FROM_CHAR: Call mktime()");
2949-
NOTICE_TM;
2950-
#endif
2951-
mktime(tm);
2952-
tm->tm_year+=1900;
2953-
tm->tm_mon+=1;
2954-
2955-
#if defined(HAVE_TM_ZONE)
2956-
tz=-(tm->tm_gmtoff);/* tm_gmtoff is Sun/DEC-ism */
2957-
#elif defined(HAVE_INT_TIMEZONE)
2958-
tz= ((tm->tm_isdst>0) ? (TIMEZONE_GLOBAL-3600) :TIMEZONE_GLOBAL);
2959-
#endif
2960-
2961-
#else/* not (HAVE_TM_ZONE || HAVE_INT_TIMEZONE) */
2962-
tz=CTimeZone;
2963-
#endif
2964-
}
2965-
else
2966-
{
2967-
tm->tm_isdst=0;
2968-
tz=0;
2969-
}
2939+
tz=DetermineLocalTimeZone(tm);
29702940
#ifdefDEBUG_TO_FROM_CHAR
29712941
NOTICE_TM;
29722942
#endif

‎src/backend/utils/adt/timestamp.c

Lines changed: 3 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.48 2001/05/0319:00:36 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.49 2001/05/0322:53:07 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -990,32 +990,7 @@ timestamp_pl_span(PG_FUNCTION_ARGS)
990990
if (tm->tm_mday>day_tab[isleap(tm->tm_year)][tm->tm_mon-1])
991991
tm->tm_mday= (day_tab[isleap(tm->tm_year)][tm->tm_mon-1]);
992992

993-
if (IS_VALID_UTIME(tm->tm_year,tm->tm_mon,tm->tm_mday))
994-
{
995-
#if defined(HAVE_TM_ZONE)|| defined(HAVE_INT_TIMEZONE)
996-
tm->tm_year-=1900;
997-
tm->tm_mon-=1;
998-
tm->tm_isdst=-1;
999-
mktime(tm);
1000-
tm->tm_year+=1900;
1001-
tm->tm_mon+=1;
1002-
1003-
#if defined(HAVE_TM_ZONE)
1004-
tz=-(tm->tm_gmtoff);/* tm_gmtoff is
1005-
* Sun/DEC-ism */
1006-
#elif defined(HAVE_INT_TIMEZONE)
1007-
tz= ((tm->tm_isdst>0) ? (TIMEZONE_GLOBAL-3600) :TIMEZONE_GLOBAL);
1008-
#endif
1009-
1010-
#else/* not (HAVE_TM_ZONE || HAVE_INT_TIMEZONE) */
1011-
tz=CTimeZone;
1012-
#endif
1013-
}
1014-
else
1015-
{
1016-
tm->tm_isdst=0;
1017-
tz=0;
1018-
}
993+
tz=DetermineLocalTimeZone(tm);
1019994

1020995
if (tm2timestamp(tm,fsec,&tz,&dt)!=0)
1021996
elog(ERROR,"Unable to add timestamp and interval");
@@ -1631,31 +1606,7 @@ timestamp_trunc(PG_FUNCTION_ARGS)
16311606
result=0;
16321607
}
16331608

1634-
if (IS_VALID_UTIME(tm->tm_year,tm->tm_mon,tm->tm_mday))
1635-
{
1636-
#if defined(HAVE_TM_ZONE)|| defined(HAVE_INT_TIMEZONE)
1637-
tm->tm_year-=1900;
1638-
tm->tm_mon-=1;
1639-
tm->tm_isdst=-1;
1640-
mktime(tm);
1641-
tm->tm_year+=1900;
1642-
tm->tm_mon+=1;
1643-
1644-
#if defined(HAVE_TM_ZONE)
1645-
tz=-(tm->tm_gmtoff);/* tm_gmtoff is Sun/DEC-ism */
1646-
#elif defined(HAVE_INT_TIMEZONE)
1647-
tz= ((tm->tm_isdst>0) ? (TIMEZONE_GLOBAL-3600) :TIMEZONE_GLOBAL);
1648-
#endif
1649-
1650-
#else/* not (HAVE_TM_ZONE || HAVE_INT_TIMEZONE) */
1651-
tz=CTimeZone;
1652-
#endif
1653-
}
1654-
else
1655-
{
1656-
tm->tm_isdst=0;
1657-
tz=0;
1658-
}
1609+
tz=DetermineLocalTimeZone(tm);
16591610

16601611
if (tm2timestamp(tm,fsec,&tz,&result)!=0)
16611612
elog(ERROR,"Unable to truncate timestamp to '%s'",lowunits);

‎src/include/utils/datetime.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
1010
* Portions Copyright (c) 1994, Regents of the University of California
1111
*
12-
* $Id: datetime.h,v 1.17 2001/01/24 19:43:28 momjian Exp $
12+
* $Id: datetime.h,v 1.18 2001/05/03 22:53:07 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -255,6 +255,8 @@ extern int DecodeDateDelta(char **field, int *ftype,
255255
intnf,int*dtype,
256256
structtm*tm,double*fsec);
257257

258+
externintDetermineLocalTimeZone(structtm*tm);
259+
258260
externintEncodeDateOnly(structtm*tm,intstyle,char*str);
259261
externintEncodeTimeOnly(structtm*tm,doublefsec,int*tzp,intstyle,char*str);
260262
externintEncodeDateTime(structtm*tm,doublefsec,int*tzp,char**tzn,intstyle,char*str);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp