]> granicus.if.org Git - postgresql/commitdiff
Reject year zero during datetime input, except when it's a 2-digit year
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 25 Feb 2008 23:36:28 +0000 (23:36 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 25 Feb 2008 23:36:28 +0000 (23:36 +0000)
(then it means 2000 AD).  Formerly we silently interpreted this as 1 BC,
which at best is unwarranted familiarity with the implementation.
It's barely possible that some app somewhere expects the old behavior,
though, so we won't back-patch this into existing release branches.

src/backend/utils/adt/datetime.c

index d8fbe0a30771862ccf4b57b89b4087df5cdc1203..08f21b46b0a1769536c740ef6c2fb5062aba8772 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.186 2008/02/25 23:21:01 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/datetime.c,v 1.187 2008/02/25 23:36:28 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2138,24 +2138,30 @@ ValidateDate(int fmask, bool is2digits, bool bc, struct pg_tm * tm)
 {
        if (fmask & DTK_M(YEAR))
        {
-               /* there is no year zero in AD/BC notation; i.e. "1 BC" == year 0 */
                if (bc)
                {
-                       if (tm->tm_year > 0)
-                               tm->tm_year = -(tm->tm_year - 1);
-                       else
-                               ereport(ERROR,
-                                               (errcode(ERRCODE_INVALID_DATETIME_FORMAT),
-                                                errmsg("inconsistent use of year %04d and \"BC\"",
-                                                               tm->tm_year)));
+                       /* there is no year zero in AD/BC notation */
+                       if (tm->tm_year <= 0)
+                               return DTERR_FIELD_OVERFLOW;
+                       /* internally, we represent 1 BC as year zero, 2 BC as -1, etc */
+                       tm->tm_year = -(tm->tm_year - 1);
                }
                else if (is2digits)
                {
+                       /* allow 2-digit input for 1970-2069 AD; 00 is allowed */
+                       if (tm->tm_year < 0)                            /* just paranoia */
+                               return DTERR_FIELD_OVERFLOW;
                        if (tm->tm_year < 70)
                                tm->tm_year += 2000;
                        else if (tm->tm_year < 100)
                                tm->tm_year += 1900;
                }
+               else
+               {
+                       /* there is no year zero in AD/BC notation */
+                       if (tm->tm_year <= 0)
+                               return DTERR_FIELD_OVERFLOW;
+               }
        }
 
        /* now that we have correct year, decode DOY */