static const datetkn *datebsearch(const char *key, const datetkn *base, int nel);
 static int DecodeDate(char *str, int fmask, int *tmask, bool *is2digits,
           struct pg_tm * tm);
-static int ValidateDate(int fmask, bool is2digits, bool bc,
+static int ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc,
             struct pg_tm * tm);
 static void TrimTrailingZeros(char *str);
 static void AppendSeconds(char *cp, int sec, fsec_t fsec,
    int         dterr;
    int         mer = HR24;
    bool        haveTextMonth = FALSE;
+   bool        isjulian = FALSE;
    bool        is2digits = FALSE;
    bool        bc = FALSE;
    pg_tz      *namedTz = NULL;
 
                    errno = 0;
                    val = strtoi(field[i], &cp, 10);
-                   if (errno == ERANGE)
+                   if (errno == ERANGE || val < 0)
                        return DTERR_FIELD_OVERFLOW;
 
                    j2date(val, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
+                   isjulian = TRUE;
+
                    /* Get the time zone from the end of the string */
                    dterr = DecodeTimezone(cp, tzp);
                    if (dterr)
                            break;
 
                        case DTK_JULIAN:
-                           /***
-                            * previous field was a label for "julian date"?
-                            ***/
+                           /* previous field was a label for "julian date" */
+                           if (val < 0)
+                               return DTERR_FIELD_OVERFLOW;
                            tmask = DTK_DATE_M;
                            j2date(val, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
+                           isjulian = TRUE;
+
                            /* fractional Julian Day? */
                            if (*cp == '.')
                            {
    }                           /* end loop over fields */
 
    /* do final checking/adjustment of Y/M/D fields */
-   dterr = ValidateDate(fmask, is2digits, bc, tm);
+   dterr = ValidateDate(fmask, isjulian, is2digits, bc, tm);
    if (dterr)
        return dterr;
 
    int         i;
    int         val;
    int         dterr;
+   bool        isjulian = FALSE;
    bool        is2digits = FALSE;
    bool        bc = FALSE;
    int         mer = HR24;
                            break;
 
                        case DTK_JULIAN:
-                           /***
-                            * previous field was a label for "julian date"?
-                            ***/
+                           /* previous field was a label for "julian date" */
+                           if (val < 0)
+                               return DTERR_FIELD_OVERFLOW;
                            tmask = DTK_DATE_M;
                            j2date(val, &tm->tm_year, &tm->tm_mon, &tm->tm_mday);
+                           isjulian = TRUE;
+
                            if (*cp == '.')
                            {
                                double      time;
    }                           /* end loop over fields */
 
    /* do final checking/adjustment of Y/M/D fields */
-   dterr = ValidateDate(fmask, is2digits, bc, tm);
+   dterr = ValidateDate(fmask, isjulian, is2digits, bc, tm);
    if (dterr)
        return dterr;
 
  * Return 0 if okay, a DTERR code if not.
  */
 static int
-ValidateDate(int fmask, bool is2digits, bool bc, struct pg_tm * tm)
+ValidateDate(int fmask, bool isjulian, bool is2digits, bool bc,
+            struct pg_tm * tm)
 {
    if (fmask & DTK_M(YEAR))
    {
-       if (bc)
+       if (isjulian)
+       {
+           /* tm_year is correct and should not be touched */
+       }
+       else if (bc)
        {
            /* there is no year zero in AD/BC notation */
            if (tm->tm_year <= 0)