Fix code to check legal dates *before* calling localtime() to get the
authorThomas G. Lockhart <lockhart@fourpalms.org>
Thu, 15 Apr 1999 02:22:39 +0000 (02:22 +0000)
committerThomas G. Lockhart <lockhart@fourpalms.org>
Thu, 15 Apr 1999 02:22:39 +0000 (02:22 +0000)
 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.

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

index c0fcf54e055db735f6db6118a24c7c70b44bb04a..bdc4b589d285fd591c448e3b252af19bfe545944 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * 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 $
  *
  *-------------------------------------------------------------------------
  */
 
 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
@@ -71,7 +58,7 @@ date_in(char *str)
 #endif
    if ((ParseDateTime(str, lowstr, field, ftype, MAXDATEFIELDS, &nf) != 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)
    {
@@ -89,19 +76,9 @@ date_in(char *str)
            break;
 
        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));
 
    return date;
@@ -453,13 +430,6 @@ time_in(char *str)
        || (DecodeTimeOnly(field, ftype, nf, &dtype, tm, &fsec) != 0))
        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 = ((((tm->tm_hour * 60) + tm->tm_min) * 60) + tm->tm_sec + fsec);
index 17a125092878ca1de383eb82728fb773a4eb5c7b..373553ed4c8334679c5fe28b69326844fa3626e1 100644 (file)
@@ -7,7 +7,7 @@
  *
  *
  * 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);
 #define USE_DATE_CACHE 1
 #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] = {
    {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}};
@@ -882,15 +876,6 @@ datetime_pl_span(DateTime *datetime, TimeSpan *span)
                }
 
                /* 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])
                    tm->tm_mday = (day_tab[isleap(tm->tm_year)][tm->tm_mon - 1]);
 
@@ -1197,21 +1182,11 @@ datetime_age(DateTime *datetime1, DateTime *datetime2)
        {
            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_mon--;
            }
            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_mon--;
            }
@@ -2302,21 +2277,6 @@ datetkn    *deltacache[MAXDATEFIELDS] = {NULL};
  * 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
 date2j(int y, int m, int d)
 {
@@ -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);
 #endif
 
-   if ((*dtype == DTK_DATE) && ((fmask & DTK_DATE_M) != DTK_DATE_M))
-       return ((fmask & DTK_TIME_M) == DTK_TIME_M) ? 1 : -1;
-
-   /* 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))))
+   /* do additional checking for full date specs... */
+   if (*dtype == DTK_DATE)
    {
+       if ((fmask & DTK_DATE_M) != DTK_DATE_M)
+           return ((fmask & DTK_TIME_M) == DTK_TIME_M) ? 1 : -1;
 
-       /*
-        * daylight savings time modifier but no standard timezone? then
-        * error
-        */
-       if (fmask & DTK_M(DTZMOD))
+       /* check for valid day of month, now that we know for sure the month and year... */
+       if ((tm->tm_mday < 1)
+        || (tm->tm_mday > day_tab[isleap(tm->tm_year)][tm->tm_mon - 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
-           tm->tm_year -= 1900;
-           tm->tm_mon -= 1;
-           tm->tm_isdst = -1;
-           mktime(tm);
-           tm->tm_year += 1900;
-           tm->tm_mon += 1;
+               tm->tm_year -= 1900;
+               tm->tm_mon -= 1;
+               tm->tm_isdst = -1;
+               mktime(tm);
+               tm->tm_year += 1900;
+               tm->tm_mon += 1;
 
 #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)
-           *tzp = ((tm->tm_isdst > 0) ? (timezone - 3600) : timezone);
+               *tzp = ((tm->tm_isdst > 0) ? (timezone - 3600) : timezone);
 #else
 #error USE_POSIX_TIME is defined but neither HAVE_TM_ZONE or HAVE_INT_TIMEZONE are defined
 #endif
 
 #else                          /* !USE_POSIX_TIME */
-           *tzp = CTimeZone;
+               *tzp = CTimeZone;
 #endif
-       }
-       else
-       {
-           tm->tm_isdst = 0;
-           *tzp = 0;
+           }
+           else
+           {
+               tm->tm_isdst = 0;
+               *tzp = 0;
+           }
        }
    }
 
@@ -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))
        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)
        return -1;
 
@@ -3541,15 +3514,6 @@ DecodeNumber(int flen, char *str, int fmask,
        tm->tm_year = val;
 
        /* 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);
 
    }
@@ -3615,13 +3579,6 @@ DecodeNumberField(int len, char *str, int fmask,
            tm->tm_mon = atoi(str + 2);
            *(str + 2) = '\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;
        }
 
@@ -3636,13 +3593,6 @@ DecodeNumberField(int len, char *str, int fmask,
        *(str + 2) = '\0';
        tm->tm_mon = 1;
        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;
    }
    else if (strchr(str, '.') != NULL)