提交 b2b3d5d1 编写于 作者: T Thomas G. Lockhart

Fix code to check legal dates *before* calling localtime() to get the

 time zone.
Previously, localtime() rotated a date with a day of month field which
 exceeded the actual range into the next months, masking the fact that
 a bad date had been specified.
Regression tests pass.
上级 64e74e30
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.30 1999/03/14 16:40:15 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.31 1999/04/15 02:22:37 thomas Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -27,19 +27,6 @@ ...@@ -27,19 +27,6 @@
static int date2tm(DateADT dateVal, int *tzp, struct tm * tm, double *fsec, char **tzn); static int date2tm(DateADT dateVal, int *tzp, struct tm * tm, double *fsec, char **tzn);
#define UTIME_MINYEAR (1901)
#define UTIME_MINMONTH (12)
#define UTIME_MINDAY (14)
#define UTIME_MAXYEAR (2038)
#define UTIME_MAXMONTH (01)
#define UTIME_MAXDAY (18)
#define IS_VALID_UTIME(y,m,d) (((y > UTIME_MINYEAR) \
|| ((y == UTIME_MINYEAR) && ((m > UTIME_MINMONTH) \
|| ((m == UTIME_MINMONTH) && (d >= UTIME_MINDAY))))) \
&& ((y < UTIME_MAXYEAR) \
|| ((y == UTIME_MAXYEAR) && ((m < UTIME_MAXMONTH) \
|| ((m == UTIME_MAXMONTH) && (d <= UTIME_MAXDAY))))))
/***************************************************************************** /*****************************************************************************
* Date ADT * Date ADT
...@@ -71,7 +58,7 @@ date_in(char *str) ...@@ -71,7 +58,7 @@ date_in(char *str)
#endif #endif
if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0) if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 0)
|| (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tzp) != 0)) || (DecodeDateTime(field, ftype, nf, &dtype, tm, &fsec, &tzp) != 0))
elog(ERROR, "Bad date external representation %s", str); elog(ERROR, "Bad date external representation '%s'", str);
switch (dtype) switch (dtype)
{ {
...@@ -89,19 +76,9 @@ date_in(char *str) ...@@ -89,19 +76,9 @@ date_in(char *str)
break; break;
default: default:
elog(ERROR, "Unrecognized date external representation %s", str); elog(ERROR, "Unrecognized date external representation '%s'", str);
} }
#ifdef NOT_USED
if (tm->tm_year < 0 || tm->tm_year > 32767)
elog(ERROR, "date_in: year must be limited to values 0 through 32767 in '%s'", str);
if (tm->tm_mon < 1 || tm->tm_mon > 12)
elog(ERROR, "date_in: month must be limited to values 1 through 12 in '%s'", str);
#endif
if (tm->tm_mday < 1 || tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
elog(ERROR, "date_in: day must be limited to values 1 through %d in '%s'",
day_tab[isleap(tm->tm_year)][tm->tm_mon - 1], str);
date = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1)); date = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1));
return date; return date;
...@@ -453,13 +430,6 @@ time_in(char *str) ...@@ -453,13 +430,6 @@ time_in(char *str)
|| (DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec) != 0)) || (DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec) != 0))
elog(ERROR, "Bad time external representation '%s'", str); elog(ERROR, "Bad time external representation '%s'", str);
if ((tm->tm_hour < 0) || (tm->tm_hour > 23))
elog(ERROR, "Hour must be limited to values 0 through 23 in '%s'", str);
if ((tm->tm_min < 0) || (tm->tm_min > 59))
elog(ERROR, "Minute must be limited to values 0 through 59 in '%s'", str);
if ((tm->tm_sec < 0) || ((tm->tm_sec + fsec) >= 60))
elog(ERROR, "Second must be limited to values 0 through < 60 in '%s'", str);
time = palloc(sizeof(TimeADT)); time = palloc(sizeof(TimeADT));
*time = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec + fsec); *time = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec + fsec);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.67 1999/03/20 02:31:45 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/dt.c,v 1.68 1999/04/15 02:22:39 thomas Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -55,12 +55,6 @@ static int tm2timespan(struct tm * tm, double fsec, TimeSpan *span); ...@@ -55,12 +55,6 @@ static int tm2timespan(struct tm * tm, double fsec, TimeSpan *span);
#define USE_DATE_CACHE 1 #define USE_DATE_CACHE 1
#define ROUND_ALL 0 #define ROUND_ALL 0
#if 0
#define isleap(y) (((y % 4) == 0) && (((y % 100) != 0) || ((y % 400) == 0)))
int mdays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0};
#endif
int day_tab[2][13] = { int day_tab[2][13] = {
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0}, {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0},
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0}}; {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0}};
...@@ -882,15 +876,6 @@ datetime_pl_span(DateTime *datetime, TimeSpan *span) ...@@ -882,15 +876,6 @@ datetime_pl_span(DateTime *datetime, TimeSpan *span)
} }
/* adjust for end of month boundary problems... */ /* adjust for end of month boundary problems... */
#if 0
if (tm->tm_mday > mdays[tm->tm_mon - 1])
{
if ((tm->tm_mon == 2) && isleap(tm->tm_year))
tm->tm_mday = (mdays[tm->tm_mon - 1] + 1);
else
tm->tm_mday = mdays[tm->tm_mon - 1];
}
#endif
if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]) if (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1])
tm->tm_mday = (day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]); tm->tm_mday = (day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]);
...@@ -1197,21 +1182,11 @@ datetime_age(DateTime *datetime1, DateTime *datetime2) ...@@ -1197,21 +1182,11 @@ datetime_age(DateTime *datetime1, DateTime *datetime2)
{ {
if (dt1 < dt2) if (dt1 < dt2)
{ {
#if 0
tm->tm_mday += mdays[tm1->tm_mon - 1];
if (isleap(tm1->tm_year) && (tm1->tm_mon == 2))
tm->tm_mday++;
#endif
tm->tm_mday += day_tab[isleap(tm1->tm_year)][tm1->tm_mon - 1]; tm->tm_mday += day_tab[isleap(tm1->tm_year)][tm1->tm_mon - 1];
tm->tm_mon--; tm->tm_mon--;
} }
else else
{ {
#if 0
tm->tm_mday += mdays[tm2->tm_mon - 1];
if (isleap(tm2->tm_year) && (tm2->tm_mon == 2))
tm->tm_mday++;
#endif
tm->tm_mday += day_tab[isleap(tm2->tm_year)][tm2->tm_mon - 1]; tm->tm_mday += day_tab[isleap(tm2->tm_year)][tm2->tm_mon - 1];
tm->tm_mon--; tm->tm_mon--;
} }
...@@ -2302,21 +2277,6 @@ datetkn *deltacache[MAXDATEFIELDS] = {NULL}; ...@@ -2302,21 +2277,6 @@ datetkn *deltacache[MAXDATEFIELDS] = {NULL};
* These routines will be used by other date/time packages - tgl 97/02/25 * These routines will be used by other date/time packages - tgl 97/02/25
*/ */
#if 0
XXX moved to dt.h - thomas 1999-01-15
/* Set the minimum year to one greater than the year of the first valid day
* to avoid having to check year and day both. - tgl 97/05/08
*/
#define JULIAN_MINYEAR (-4713)
#define JULIAN_MINMONTH (11)
#define JULIAN_MINDAY (23)
#define IS_VALID_JULIAN(y,m,d) ((y > JULIAN_MINYEAR) \
|| ((y == JULIAN_MINYEAR) && ((m > JULIAN_MINMONTH) \
|| ((m == JULIAN_MINMONTH) && (d >= JULIAN_MINDAY)))))
#endif
int int
date2j(int y, int m, int d) date2j(int y, int m, int d)
{ {
...@@ -3063,47 +3023,55 @@ DecodeDateTime(char **field, int *ftype, int nf, ...@@ -3063,47 +3023,55 @@ DecodeDateTime(char **field, int *ftype, int nf,
printf(" %02d:%02d:%02d\n", tm->tm_hour, tm->tm_min, tm->tm_sec); printf(" %02d:%02d:%02d\n", tm->tm_hour, tm->tm_min, tm->tm_sec);
#endif #endif
if ((*dtype == DTK_DATE) && ((fmask & DTK_DATE_M) != DTK_DATE_M)) /* do additional checking for full date specs... */
return ((fmask & DTK_TIME_M) == DTK_TIME_M) ? 1 : -1; if (*dtype == DTK_DATE)
/* timezone not specified? then find local timezone if possible */
if ((*dtype == DTK_DATE) && ((fmask & DTK_DATE_M) == DTK_DATE_M)
&& (tzp != NULL) && (!(fmask & DTK_M(TZ))))
{ {
if ((fmask & DTK_DATE_M) != DTK_DATE_M)
return ((fmask & DTK_TIME_M) == DTK_TIME_M) ? 1 : -1;
/* /* check for valid day of month, now that we know for sure the month and year... */
* daylight savings time modifier but no standard timezone? then if ((tm->tm_mday < 1)
* error || (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]))
*/
if (fmask & DTK_M(DTZMOD))
return -1; return -1;
if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday)) /* timezone not specified? then find local timezone if possible */
if (((fmask & DTK_DATE_M) == DTK_DATE_M)
&& (tzp != NULL) && (!(fmask & DTK_M(TZ))))
{ {
/*
* daylight savings time modifier but no standard timezone? then
* error
*/
if (fmask & DTK_M(DTZMOD))
return -1;
if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday))
{
#ifdef USE_POSIX_TIME #ifdef USE_POSIX_TIME
tm->tm_year -= 1900; tm->tm_year -= 1900;
tm->tm_mon -= 1; tm->tm_mon -= 1;
tm->tm_isdst = -1; tm->tm_isdst = -1;
mktime(tm); mktime(tm);
tm->tm_year += 1900; tm->tm_year += 1900;
tm->tm_mon += 1; tm->tm_mon += 1;
#if defined(HAVE_TM_ZONE) #if defined(HAVE_TM_ZONE)
*tzp = -(tm->tm_gmtoff); /* tm_gmtoff is Sun/DEC-ism */ *tzp = -(tm->tm_gmtoff); /* tm_gmtoff is Sun/DEC-ism */
#elif defined(HAVE_INT_TIMEZONE) #elif defined(HAVE_INT_TIMEZONE)
*tzp = ((tm->tm_isdst > 0) ? (timezone - 3600) : timezone); *tzp = ((tm->tm_isdst > 0) ? (timezone - 3600) : timezone);
#else #else
#error USE_POSIX_TIME is defined but neither HAVE_TM_ZONE or HAVE_INT_TIMEZONE are defined #error USE_POSIX_TIME is defined but neither HAVE_TM_ZONE or HAVE_INT_TIMEZONE are defined
#endif #endif
#else /* !USE_POSIX_TIME */ #else /* !USE_POSIX_TIME */
*tzp = CTimeZone; *tzp = CTimeZone;
#endif #endif
} }
else else
{ {
tm->tm_isdst = 0; tm->tm_isdst = 0;
*tzp = 0; *tzp = 0;
}
} }
} }
...@@ -3231,6 +3199,11 @@ DecodeTimeOnly(char **field, int *ftype, int nf, int *dtype, struct tm * tm, dou ...@@ -3231,6 +3199,11 @@ DecodeTimeOnly(char **field, int *ftype, int nf, int *dtype, struct tm * tm, dou
else if ((mer == PM) && (tm->tm_hour != 12)) else if ((mer == PM) && (tm->tm_hour != 12))
tm->tm_hour += 12; tm->tm_hour += 12;
if (((tm->tm_hour < 0) || (tm->tm_hour > 23))
|| ((tm->tm_min < 0) || (tm->tm_min > 59))
|| ((tm->tm_sec < 0) || ((tm->tm_sec + *fsec) >= 60)))
return -1;
if ((fmask & DTK_TIME_M) != DTK_TIME_M) if ((fmask & DTK_TIME_M) != DTK_TIME_M)
return -1; return -1;
...@@ -3541,15 +3514,6 @@ DecodeNumber(int flen, char *str, int fmask, ...@@ -3541,15 +3514,6 @@ DecodeNumber(int flen, char *str, int fmask,
tm->tm_year = val; tm->tm_year = val;
/* adjust ONLY if exactly two digits... */ /* adjust ONLY if exactly two digits... */
#if 0
if (flen == 2)
{
if (tm->tm_year < 70)
tm->tm_year += 2000;
else if (tm->tm_year < 100)
tm->tm_year += 1900;
}
#endif
*is2digits = (flen == 2); *is2digits = (flen == 2);
} }
...@@ -3615,13 +3579,6 @@ DecodeNumberField(int len, char *str, int fmask, ...@@ -3615,13 +3579,6 @@ DecodeNumberField(int len, char *str, int fmask,
tm->tm_mon = atoi(str + 2); tm->tm_mon = atoi(str + 2);
*(str + 2) = '\0'; *(str + 2) = '\0';
tm->tm_year = atoi(str + 0); tm->tm_year = atoi(str + 0);
#if 0
if (tm->tm_year < 70)
tm->tm_year += 2000;
else if (tm->tm_year < 100)
tm->tm_year += 1900;
#endif
*is2digits = TRUE; *is2digits = TRUE;
} }
...@@ -3636,13 +3593,6 @@ DecodeNumberField(int len, char *str, int fmask, ...@@ -3636,13 +3593,6 @@ DecodeNumberField(int len, char *str, int fmask,
*(str + 2) = '\0'; *(str + 2) = '\0';
tm->tm_mon = 1; tm->tm_mon = 1;
tm->tm_year = atoi(str + 0); tm->tm_year = atoi(str + 0);
#if 0
if (tm->tm_year < 70)
tm->tm_year += 2000;
else if (tm->tm_year < 100)
tm->tm_year += 1900;
#endif
*is2digits = TRUE; *is2digits = TRUE;
} }
else if (strchr(str, '.') != NULL) else if (strchr(str, '.') != NULL)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册