agora inbox for pgsql-bugs@postgresql.org  
help / color / mirror / Atom feed
BUG #19650: to_date()/to_timestamp() silently truncate 4+-digit day-of-year input to the first three digits
3+ messages / 3 participants
[nested] [flat]

* BUG #19650: to_date()/to_timestamp() silently truncate 4+-digit day-of-year input to the first three digits
@ 2026-09-03 06:45 PG Bug reporting form <noreply@postgresql.org>
  2026-09-03 15:29 ` Re: BUG #19650: to_date()/to_timestamp() silently truncate 4+-digit day-of-year input to the first three digits Andrey Rachitskiy <pl0h0yp1@gmail.com>
  0 siblings, 1 reply; 3+ messages in thread

From: PG Bug reporting form @ 2026-09-03 06:45 UTC (permalink / raw)
  To: pgsql-bugs@lists.postgresql.org; +Cc: 303677365@qq.com

The following bug has been logged on the website:

Bug reference:      19650
Logged by:          chunling qin
Email address:      303677365@qq.com
PostgreSQL version: 18.6
Operating system:   x86_64
Description:        

The documentation states that DDD (day of year) accepts values 001-366 and
IDDD (ISO day of year) 001-371, and out-of-range values raise an error. That
check works for 3-digit input, but for input of 4 or more digits the parser
silently keeps only the first three digits and treats them as a valid day
number:

SELECT to_date('2024 1000', 'YYYY DDDD');
-- 2024-04-09      (parsed as day 100 — the first three digits)

SELECT to_date('2024 1234', 'YYYY DDDD');
-- 2024-05-02      (parsed as day 123)

SELECT to_date('2024 10000', 'YYYY DDDD');
-- 2024-04-09      (5-digit input, still day 100)

SELECT to_date('2024 999', 'IYYY IDDD');
-- 2026-09-25      (IDDD 999 silently accepted; an ISO year has at most 371
days)

```
hunt@(null)=# SELECT to_date('2024 1000', 'YYYY DDDD');
-- 2024-04-09      (parsed as day 100 — the first three digits)

SELECT to_date('2024 1234', 'YYYY DDDD');
-- 2024-05-02      (parsed as day 123)

SELECT to_date('2024 10000', 'YYYY DDDD');
-- 2024-04-09      (5-digit input, still day 100)

SELECT to_date('2024 999', 'IYYY IDDD');
-- 2026-09-25      (IDDD 999 silently accepted; an ISO year has at most 371
days)
  to_date
------------
 2024-04-09
(1 row)

  to_date
------------
 2024-05-02
(1 row)

  to_date
------------
 2024-04-09
(1 row)

  to_date
------------
 2026-09-25
(1 row)

hunt@(null)=# SELECT to_date('2024 367', 'YYYY DDD');
-- ERROR:  date/time field value out of range: "2024 367"
ERROR:  date/time field value out of range: "2024 367"
```








^ permalink  raw  reply  [nested|flat] 3+ messages in thread

* Re: BUG #19650: to_date()/to_timestamp() silently truncate 4+-digit day-of-year input to the first three digits
  2026-09-03 06:45 BUG #19650: to_date()/to_timestamp() silently truncate 4+-digit day-of-year input to the first three digits PG Bug reporting form <noreply@postgresql.org>
@ 2026-09-03 15:29 ` Andrey Rachitskiy <pl0h0yp1@gmail.com>
  2026-09-09 04:31   ` Re: BUG #19650: to_date()/to_timestamp() silently truncate 4+-digit day-of-year input to the first three digits Clemenza Zhang <zxlmgsps2@gmail.com>
  0 siblings, 1 reply; 3+ messages in thread

From: Andrey Rachitskiy @ 2026-09-03 15:29 UTC (permalink / raw)
  To: 303677365@qq.com; pgsql-bugs@lists.postgresql.org

чт, 3 сент. 2026 г. в 18:02, PG Bug reporting form <noreply@postgresql.org>:

> The following bug has been logged on the website:
>
> Bug reference:      19650
> Logged by:          chunling qin
> Email address:      303677365@qq.com
> PostgreSQL version: 18.6
> Operating system:   x86_64
> Description:
>
> The documentation states that DDD (day of year) accepts values 001-366 and
> IDDD (ISO day of year) 001-371, and out-of-range values raise an error.
> That
> check works for 3-digit input, but for input of 4 or more digits the parser
> silently keeps only the first three digits and treats them as a valid day
> number:
>
> SELECT to_date('2024 1000', 'YYYY DDDD');
> -- 2024-04-09      (parsed as day 100 — the first three digits)
>
> SELECT to_date('2024 1234', 'YYYY DDDD');
> -- 2024-05-02      (parsed as day 123)
>
> SELECT to_date('2024 10000', 'YYYY DDDD');
> -- 2024-04-09      (5-digit input, still day 100)
>
> SELECT to_date('2024 999', 'IYYY IDDD');
> -- 2026-09-25      (IDDD 999 silently accepted; an ISO year has at most 371
> days)
>
> ```
> hunt@(null)=# SELECT to_date('2024 1000', 'YYYY DDDD');
> -- 2024-04-09      (parsed as day 100 — the first three digits)
>
> SELECT to_date('2024 1234', 'YYYY DDDD');
> -- 2024-05-02      (parsed as day 123)
>
> SELECT to_date('2024 10000', 'YYYY DDDD');
> -- 2024-04-09      (5-digit input, still day 100)
>
> SELECT to_date('2024 999', 'IYYY IDDD');
> -- 2026-09-25      (IDDD 999 silently accepted; an ISO year has at most 371
> days)
>   to_date
> ------------
>  2024-04-09
> (1 row)
>
>   to_date
> ------------
>  2024-05-02
> (1 row)
>
>   to_date
> ------------
>  2024-04-09
> (1 row)
>
>   to_date
> ------------
>  2026-09-25
> (1 row)
>
> hunt@(null)=# SELECT to_date('2024 367', 'YYYY DDD');
> -- ERROR:  date/time field value out of range: "2024 367"
> ERROR:  date/time field value out of range: "2024 367"
> ```
>
>
Hi!

Thanks for the report.

The holes are:

  DDD / IDDD   001-366 / 001-371
  SSSSS        0-86399
  RM           I-XII
  IW           01-53   (WW 54+ already errored before; now checked
uniformly)
  ID           1-7

YYYY DDDD parses as YYYY + DDD + weekday D.  D is accepted but
ignored for date computation, so to_date('2024 1000', 'YYYY DDDD')
is not a DDD overflow case.  to_date('2024 1000', 'YYYY DDD')
already failed, and still does.

The checks run when the field is parsed.  A later 0 in TmFromChar
means the field was unset, so ID 0 and IW 0 cannot be rejected in
do_to_timestamp.  SSSSS recovers a minus that was swallowed as a
separator, the same way TZH does.  RM rejects a leftover roman
digit so XIII is not taken as XII.

Patch with regress in attachment.


-- 
Regards,
Rachitskiy Andrey

Attachments:

  [text/x-patch] 0001-Reject-out-of-range-to_date-to_timestamp-template.patch (9.1K, ../../CAB8bMiu9+9H_fNCD_i3D-Q4rz6oCJJGNvtZDgx-8FKiToSO2=g@mail.gmail.com/3-0001-Reject-out-of-range-to_date-to_timestamp-template.patch)
  download | inline diff:
From 6effdee19cdbe1ed6ea1cf6d958ce839678f41a5 Mon Sep 17 00:00:00 2001
From: Andrey Rachitskiy <pl0h0yp1@gmail.com>
Date: Thu, 3 Sep 2026 20:18:06 +0500
Subject: [PATCH] Reject out-of-range to_date/to_timestamp template fields.

DDD, IDDD, SSSSS, RM, IW, and ID accepted values outside their documented domains.
Check the parsed field at read time, because a later 0 means the field was unset.
Recover a minus swallowed as a separator before SSSSS, matching TZH.
Reject leftover roman digits after RM, so XIII is not taken as XII.

Bug: #19650,19651
Author: Andrey Rachitskiy <pl0h0yp1@gmail.com>
Reported-by: chunling qin <303677365@qq.com>
---
 src/backend/utils/adt/formatting.c     | 70 ++++++++++++++++++++++++--
 src/test/regress/expected/horology.out | 44 ++++++++++++++++
 src/test/regress/sql/horology.sql      | 14 ++++++
 3 files changed, 123 insertions(+), 5 deletions(-)

diff --git a/src/backend/utils/adt/formatting.c b/src/backend/utils/adt/formatting.c
index 900fa8f20e5..569d4252e5b 100644
--- a/src/backend/utils/adt/formatting.c
+++ b/src/backend/utils/adt/formatting.c
@@ -1093,6 +1093,8 @@ static bool from_char_set_mode(TmFromChar *tmfc, const FromCharDateMode mode,
 							   Node *escontext);
 static bool from_char_set_int(int *dest, const int value, const FormatNode *node,
 							  Node *escontext);
+static bool from_char_in_range(int value, int min, int max, const char *in,
+							   Node *escontext);
 static int	from_char_parse_int_len(int *dest, const char **src, const size_t len,
 									FormatNode *node, Node *escontext);
 static int	from_char_parse_int(int *dest, const char **src, FormatNode *node,
@@ -2156,6 +2158,26 @@ from_char_set_int(int *dest, const int value, const FormatNode *node,
 	return true;
 }
 
+/*
+ * Check that 'value' lies in [min, max].
+ *
+ * Puke if it does not.  This must run at parse time: a later 0 means
+ * the field was unset.
+ *
+ * Returns true on success, false on failure (if escontext points to an
+ * ErrorSaveContext; otherwise errors are thrown).
+ */
+static bool
+from_char_in_range(int value, int min, int max, const char *in,
+				   Node *escontext)
+{
+	if (value < min || value > max)
+		ereturn(escontext, false,
+				(errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
+				 errmsg("date/time field value out of range: \"%s\"", in)));
+	return true;
+}
+
 /*
  * Read a single integer from the source string, into the int pointed to by
  * 'dest'. If 'dest' is NULL, the result is discarded.
@@ -3293,10 +3315,27 @@ DCH_from_char(FormatNode *node, const char *in, TmFromChar *out,
 				SKIP_THth(s, n->suffix);
 				break;
 			case DCH_SSSS:
-				if (from_char_parse_int(&out->ssss, &s, n, escontext) < 0)
-					return;
-				SKIP_THth(s, n->suffix);
-				break;
+				{
+					bool		neg = false;
+
+					/* Minus may have been taken as a separator (see TZH). */
+					if (*s == '+' || *s == '-')
+					{
+						neg = (*s == '-');
+						s++;
+					}
+					else if (extra_skip > 0 && *(s - 1) == '-')
+						neg = true;
+					if (from_char_parse_int(&out->ssss, &s, n, escontext) < 0)
+						return;
+					if (neg)
+						out->ssss = -out->ssss;
+					if (!from_char_in_range(out->ssss, 0, SECS_PER_DAY - 1,
+											in, escontext))
+						return;
+					SKIP_THth(s, n->suffix);
+					break;
+				}
 			case DCH_tz:
 			case DCH_TZ:
 				{
@@ -3464,11 +3503,17 @@ DCH_from_char(FormatNode *node, const char *in, TmFromChar *out,
 			case DCH_DDD:
 				if (from_char_parse_int(&out->ddd, &s, n, escontext) < 0)
 					return;
+				/* DDD is documented as day 001 to 366 of Gregorian year. */
+				if (!from_char_in_range(out->ddd, 1, 366, in, escontext))
+					return;
 				SKIP_THth(s, n->suffix);
 				break;
 			case DCH_IDDD:
 				if (from_char_parse_int_len(&out->ddd, &s, 3, n, escontext) < 0)
 					return;
+				/* IDDD is documented as day 001 to 371 of ISO year. */
+				if (!from_char_in_range(out->ddd, 1, 371, in, escontext))
+					return;
 				SKIP_THth(s, n->suffix);
 				break;
 			case DCH_DD:
@@ -3484,8 +3529,10 @@ DCH_from_char(FormatNode *node, const char *in, TmFromChar *out,
 			case DCH_ID:
 				if (from_char_parse_int_len(&out->d, &s, 1, n, escontext) < 0)
 					return;
+				if (!from_char_in_range(out->d, 1, DAYS_PER_WEEK, in, escontext))
+					return;
 				/* Shift numbering to match Gregorian where Sunday = 1 */
-				if (++out->d > 7)
+				if (++out->d > DAYS_PER_WEEK)
 					out->d = 1;
 				SKIP_THth(s, n->suffix);
 				break;
@@ -3493,6 +3540,9 @@ DCH_from_char(FormatNode *node, const char *in, TmFromChar *out,
 			case DCH_IW:
 				if (from_char_parse_int(&out->ww, &s, n, escontext) < 0)
 					return;
+				/* IW/WW are documented as week 01 to 53. */
+				if (!from_char_in_range(out->ww, 1, 53, in, escontext))
+					return;
 				SKIP_THth(s, n->suffix);
 				break;
 			case DCH_Q:
@@ -3586,6 +3636,16 @@ DCH_from_char(FormatNode *node, const char *in, TmFromChar *out,
 										  NULL, InvalidOid,
 										  n, escontext))
 					return;
+				{
+					unsigned char c = pg_ascii_toupper((unsigned char) *s);
+
+					/* leftover roman: XIII would match XII */
+					if (c == 'I' || c == 'V' || c == 'X')
+						ereturn(escontext,,
+								(errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
+								 errmsg("date/time field value out of range: \"%s\"",
+										in)));
+				}
 				if (!from_char_set_int(&out->mm, MONTHS_PER_YEAR - value, n,
 									   escontext))
 					return;
diff --git a/src/test/regress/expected/horology.out b/src/test/regress/expected/horology.out
index 32cf62b6741..7e1ea25f99a 100644
--- a/src/test/regress/expected/horology.out
+++ b/src/test/regress/expected/horology.out
@@ -3770,6 +3770,8 @@ SELECT to_timestamp('2015-02-11 86000', 'YYYY-MM-DD SSSSS');  -- ok
 
 SELECT to_timestamp('2015-02-11 86400', 'YYYY-MM-DD SSSSS');
 ERROR:  date/time field value out of range: "2015-02-11 86400"
+SELECT to_timestamp('2024-01-01 -1', 'YYYY-MM-DD SSSSS');
+ERROR:  date/time field value out of range: "2024-01-01 -1"
 SELECT to_timestamp('1000000000,999', 'Y,YYY');
 ERROR:  value for "Y,YYY" in source string is out of range
 SELECT to_timestamp('0.-2147483648', 'SS.MS');
@@ -3812,6 +3814,48 @@ SELECT to_date('2016 366', 'YYYY DDD');  -- ok
 
 SELECT to_date('2016 367', 'YYYY DDD');
 ERROR:  date/time field value out of range: "2016 367"
+SELECT to_date('2024 1000', 'YYYY DDD');
+ERROR:  date/time field value out of range: "2024 1000"
+SELECT to_date('2024 999', 'IYYY IDDD');
+ERROR:  date/time field value out of range: "2024 999"
+SELECT to_date('2024 372', 'IYYY IDDD');
+ERROR:  date/time field value out of range: "2024 372"
+SELECT to_date('2024 371', 'IYYY IDDD');  -- ok
+  to_date   
+------------
+ 01-05-2025
+(1 row)
+
+SELECT to_date('2024 XIII', 'YYYY RM');
+ERROR:  date/time field value out of range: "2024 XIII"
+SELECT to_date('2024 IIII', 'YYYY RM');
+ERROR:  date/time field value out of range: "2024 IIII"
+SELECT to_date('2024 XII', 'YYYY RM');  -- ok
+  to_date   
+------------
+ 12-01-2024
+(1 row)
+
+SELECT to_date('2024 54', 'IYYY IW');
+ERROR:  date/time field value out of range: "2024 54"
+SELECT to_date('2024 99', 'IYYY IW');
+ERROR:  date/time field value out of range: "2024 99"
+SELECT to_date('2024 53', 'IYYY IW');  -- ok
+  to_date   
+------------
+ 12-30-2024
+(1 row)
+
+SELECT to_date('2024 01 8', 'IYYY IW ID');
+ERROR:  date/time field value out of range: "2024 01 8"
+SELECT to_date('2024 01 0', 'IYYY IW ID');
+ERROR:  date/time field value out of range: "2024 01 0"
+SELECT to_date('2024 01 7', 'IYYY IW ID');  -- ok
+  to_date   
+------------
+ 01-07-2024
+(1 row)
+
 SELECT to_date('0000-02-01','YYYY-MM-DD');  -- allowed, though it shouldn't be
     to_date    
 ---------------
diff --git a/src/test/regress/sql/horology.sql b/src/test/regress/sql/horology.sql
index 8978249a5dc..889e88e6016 100644
--- a/src/test/regress/sql/horology.sql
+++ b/src/test/regress/sql/horology.sql
@@ -656,6 +656,7 @@ SELECT to_timestamp('2015-02-11 86000', 'YYYY-MM-DD SSSS');  -- ok
 SELECT to_timestamp('2015-02-11 86400', 'YYYY-MM-DD SSSS');
 SELECT to_timestamp('2015-02-11 86000', 'YYYY-MM-DD SSSSS');  -- ok
 SELECT to_timestamp('2015-02-11 86400', 'YYYY-MM-DD SSSSS');
+SELECT to_timestamp('2024-01-01 -1', 'YYYY-MM-DD SSSSS');
 SELECT to_timestamp('1000000000,999', 'Y,YYY');
 SELECT to_timestamp('0.-2147483648', 'SS.MS');
 SELECT to_timestamp('613566758', 'W');
@@ -669,6 +670,19 @@ SELECT to_date('2015 366', 'YYYY DDD');
 SELECT to_date('2016 365', 'YYYY DDD');  -- ok
 SELECT to_date('2016 366', 'YYYY DDD');  -- ok
 SELECT to_date('2016 367', 'YYYY DDD');
+SELECT to_date('2024 1000', 'YYYY DDD');
+SELECT to_date('2024 999', 'IYYY IDDD');
+SELECT to_date('2024 372', 'IYYY IDDD');
+SELECT to_date('2024 371', 'IYYY IDDD');  -- ok
+SELECT to_date('2024 XIII', 'YYYY RM');
+SELECT to_date('2024 IIII', 'YYYY RM');
+SELECT to_date('2024 XII', 'YYYY RM');  -- ok
+SELECT to_date('2024 54', 'IYYY IW');
+SELECT to_date('2024 99', 'IYYY IW');
+SELECT to_date('2024 53', 'IYYY IW');  -- ok
+SELECT to_date('2024 01 8', 'IYYY IW ID');
+SELECT to_date('2024 01 0', 'IYYY IW ID');
+SELECT to_date('2024 01 7', 'IYYY IW ID');  -- ok
 SELECT to_date('0000-02-01','YYYY-MM-DD');  -- allowed, though it shouldn't be
 SELECT to_date('100000000', 'CC');
 SELECT to_date('-100000000', 'CC');
-- 
2.53.0



^ permalink  raw  reply  [nested|flat] 3+ messages in thread

* Re: BUG #19650: to_date()/to_timestamp() silently truncate 4+-digit day-of-year input to the first three digits
  2026-09-03 06:45 BUG #19650: to_date()/to_timestamp() silently truncate 4+-digit day-of-year input to the first three digits PG Bug reporting form <noreply@postgresql.org>
  2026-09-03 15:29 ` Re: BUG #19650: to_date()/to_timestamp() silently truncate 4+-digit day-of-year input to the first three digits Andrey Rachitskiy <pl0h0yp1@gmail.com>
@ 2026-09-09 04:31   ` Clemenza Zhang <zxlmgsps2@gmail.com>
  0 siblings, 0 replies; 3+ messages in thread

From: Clemenza Zhang @ 2026-09-09 04:31 UTC (permalink / raw)
  To: Andrey Rachitskiy <pl0h0yp1@gmail.com>; +Cc: 303677365@qq.com; pgsql-bugs@lists.postgresql.org

Hi Andrey,

I tested the patch locally against current master (20devel).
The original out-of-range cases are rejected with the patch applied.  I
also tested the boundaries and a few related cases.

For SSSSS, the patch fixes the negative-value case while preserving the
existing valid boundaries:
```
SSSSS = -1      ERROR
SSSSS = 0       accepted
SSSSS = 86399   accepted
SSSSS = 86400   ERROR
```
In particular, on unpatched master
```
to_timestamp('2024-01-01 -1', 'YYYY-MM-DD SSSSS')
```
returns 00:00:01, while with the patch it correctly reports an
out-of-range error.
I also checked the other fields covered by the patch:
```
RM:    XII accepted, XIII rejected
IW:    00 rejected, 01..53 accepted, 54 rejected
ID:    0 rejected, 1..7 accepted, 8 rejected
DDD:   001..366 is still subject to the existing year-aware check
IDDD:  001..371 accepted, 372 rejected
```
I checked some ISO boundary combinations as well.  The patch retains the
existing normalization behavior for values that are within the field's
documented range.  For example, IW 53 in an ISO year that does not
actually have week 53 rolls into the following ISO year:
```
2019 53 1 -> 2019-12-30 -> 2020-01-1
2020 53 1 -> 2020-12-28 -> 2020-53-1
2024 53 1 -> 2024-12-30 -> 2025-01-1
2026 53 1 -> 2026-12-28 -> 2026-53-1
```
Similarly,
```
to_date('2024 371', 'IYYY IDDD')
```
returns 2025-01-05.  So the new checks appear to be limited to the
documented ranges for the ISO fields and do not otherwise change their
normalization semantics.

I also verified the DDDD case discussed earlier.  Inputs such as
```
to_date('2024 1000', 'YYYY DDDD')
to_date('2024 1234', 'YYYY DDDD')
```
remain accepted, consistent with DDDD being parsed as DDD followed by D.

The regression tests pass with the patch applied.

Best Regards!
Clemenza Zhang

On Thu, Sep 3, 2026 at 11:29 PM Andrey Rachitskiy <pl0h0yp1@gmail.com> wrote:
>
>
> чт, 3 сент. 2026 г. в 18:02, PG Bug reporting form <noreply@postgresql.org>:
>>
>> The following bug has been logged on the website:
>>
>> Bug reference:      19650
>> Logged by:          chunling qin
>> Email address:      303677365@qq.com
>> PostgreSQL version: 18.6
>> Operating system:   x86_64
>> Description:
>>
>> The documentation states that DDD (day of year) accepts values 001-366 and
>> IDDD (ISO day of year) 001-371, and out-of-range values raise an error. That
>> check works for 3-digit input, but for input of 4 or more digits the parser
>> silently keeps only the first three digits and treats them as a valid day
>> number:
>>
>> SELECT to_date('2024 1000', 'YYYY DDDD');
>> -- 2024-04-09      (parsed as day 100 — the first three digits)
>>
>> SELECT to_date('2024 1234', 'YYYY DDDD');
>> -- 2024-05-02      (parsed as day 123)
>>
>> SELECT to_date('2024 10000', 'YYYY DDDD');
>> -- 2024-04-09      (5-digit input, still day 100)
>>
>> SELECT to_date('2024 999', 'IYYY IDDD');
>> -- 2026-09-25      (IDDD 999 silently accepted; an ISO year has at most 371
>> days)
>>
>> ```
>> hunt@(null)=# SELECT to_date('2024 1000', 'YYYY DDDD');
>> -- 2024-04-09      (parsed as day 100 — the first three digits)
>>
>> SELECT to_date('2024 1234', 'YYYY DDDD');
>> -- 2024-05-02      (parsed as day 123)
>>
>> SELECT to_date('2024 10000', 'YYYY DDDD');
>> -- 2024-04-09      (5-digit input, still day 100)
>>
>> SELECT to_date('2024 999', 'IYYY IDDD');
>> -- 2026-09-25      (IDDD 999 silently accepted; an ISO year has at most 371
>> days)
>>   to_date
>> ------------
>>  2024-04-09
>> (1 row)
>>
>>   to_date
>> ------------
>>  2024-05-02
>> (1 row)
>>
>>   to_date
>> ------------
>>  2024-04-09
>> (1 row)
>>
>>   to_date
>> ------------
>>  2026-09-25
>> (1 row)
>>
>> hunt@(null)=# SELECT to_date('2024 367', 'YYYY DDD');
>> -- ERROR:  date/time field value out of range: "2024 367"
>> ERROR:  date/time field value out of range: "2024 367"
>> ```
>>
>
> Hi!
>
> Thanks for the report.
>
> The holes are:
>
>   DDD / IDDD   001-366 / 001-371
>   SSSSS        0-86399
>   RM           I-XII
>   IW           01-53   (WW 54+ already errored before; now checked uniformly)
>   ID           1-7
>
> YYYY DDDD parses as YYYY + DDD + weekday D.  D is accepted but
> ignored for date computation, so to_date('2024 1000', 'YYYY DDDD')
> is not a DDD overflow case.  to_date('2024 1000', 'YYYY DDD')
> already failed, and still does.
>
> The checks run when the field is parsed.  A later 0 in TmFromChar
> means the field was unset, so ID 0 and IW 0 cannot be rejected in
> do_to_timestamp.  SSSSS recovers a minus that was swallowed as a
> separator, the same way TZH does.  RM rejects a leftover roman
> digit so XIII is not taken as XII.
>
> Patch with regress in attachment.
>
>
> --
> Regards,
> Rachitskiy Andrey






^ permalink  raw  reply  [nested|flat] 3+ messages in thread


end of thread, other threads:[~2026-09-09 04:31 UTC | newest]

Thread overview: 3+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2026-09-03 06:45 BUG #19650: to_date()/to_timestamp() silently truncate 4+-digit day-of-year input to the first three digits PG Bug reporting form <noreply@postgresql.org>
2026-09-03 15:29 ` Andrey Rachitskiy <pl0h0yp1@gmail.com>
2026-09-09 04:31   ` Clemenza Zhang <zxlmgsps2@gmail.com>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox