diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/backend/utils/adt/datetime.c | 37 | ||||
| -rw-r--r-- | src/test/regress/expected/horology.out | 13 | ||||
| -rw-r--r-- | src/test/regress/sql/horology.sql | 3 | 
3 files changed, 41 insertions, 12 deletions
diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c index 8e342a9837f..705fcf195c2 100644 --- a/src/backend/utils/adt/datetime.c +++ b/src/backend/utils/adt/datetime.c @@ -42,7 +42,7 @@ static int	DecodeTimezone(char *str, int *tzp);  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, @@ -795,6 +795,7 @@ DecodeDateTime(char **field, int *ftype, int nf,  	int			dterr;  	int			mer = HR24;  	bool		haveTextMonth = FALSE; +	bool		isjulian = FALSE;  	bool		is2digits = FALSE;  	bool		bc = FALSE;  	pg_tz	   *namedTz = NULL; @@ -833,10 +834,12 @@ DecodeDateTime(char **field, int *ftype, int nf,  					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) @@ -1065,11 +1068,13 @@ DecodeDateTime(char **field, int *ftype, int nf,  							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 == '.')  							{ @@ -1361,7 +1366,7 @@ DecodeDateTime(char **field, int *ftype, int nf,  	}							/* 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; @@ -1564,6 +1569,7 @@ DecodeTimeOnly(char **field, int *ftype, int nf,  	int			i;  	int			val;  	int			dterr; +	bool		isjulian = FALSE;  	bool		is2digits = FALSE;  	bool		bc = FALSE;  	int			mer = HR24; @@ -1795,11 +1801,13 @@ DecodeTimeOnly(char **field, int *ftype, int nf,  							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; @@ -2045,7 +2053,7 @@ DecodeTimeOnly(char **field, int *ftype, int nf,  	}							/* 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; @@ -2247,11 +2255,16 @@ DecodeDate(char *str, int fmask, int *tmask, bool *is2digits,   * 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) diff --git a/src/test/regress/expected/horology.out b/src/test/regress/expected/horology.out index 26d7541b720..b13f7d7c5b5 100644 --- a/src/test/regress/expected/horology.out +++ b/src/test/regress/expected/horology.out @@ -264,6 +264,19 @@ SELECT time with time zone 'T040506.789 -08';  (1 row)  SET DateStyle = 'Postgres, MDY'; +-- Check Julian dates BC +SELECT date 'J1520447' AS "Confucius' Birthday"; + Confucius' Birthday  +--------------------- + 09-28-0551 BC +(1 row) + +SELECT date 'J0' AS "Julian Epoch"; + Julian Epoch   +--------------- + 11-24-4714 BC +(1 row) +  --  -- date, time arithmetic  -- diff --git a/src/test/regress/sql/horology.sql b/src/test/regress/sql/horology.sql index 615755e3de0..97ff9f20c79 100644 --- a/src/test/regress/sql/horology.sql +++ b/src/test/regress/sql/horology.sql @@ -56,6 +56,9 @@ SELECT time with time zone 'T040506.789-08';  SELECT time with time zone 'T040506.789 +08';  SELECT time with time zone 'T040506.789 -08';  SET DateStyle = 'Postgres, MDY'; +-- Check Julian dates BC +SELECT date 'J1520447' AS "Confucius' Birthday"; +SELECT date 'J0' AS "Julian Epoch";  --  -- date, time arithmetic  | 
