mirror of
https://github.com/postgres/postgres.git
synced 2025-07-31 22:04:40 +03:00
Improve behavior of to_timestamp()/to_date() functions
to_timestamp()/to_date() functions were introduced mainly for Oracle compatibility, and became very popular among PostgreSQL users. However, some behavior of to_timestamp()/to_date() functions are both incompatible with Oracle and confusing for our users. This behavior is related to handling of spaces and separators in non FX (fixed format) mode. This commit reworks this behavior making less confusing, better documented and more compatible with Oracle. Nevertheless, there are still following incompatibilities with Oracle. 1) We don't insist that there are no format string patterns unmatched to input string. 2) In FX mode we don't insist space and separators in format string to exactly match input string. 3) When format string patterns are divided by mix of spaces and separators, we don't distinguish them, while Oracle takes into account only last group of spaces/separators. Discussion: https://postgr.es/m/1873520224.1784572.1465833145330.JavaMail.yahoo%40mail.yahoo.com Author: Artur Zakirov, Alexander Korotkov, Liudmila Mantrova Review: Amul Sul, Robert Haas, Tom Lane, Dmitry Dolgov, David G. Johnston
This commit is contained in:
@ -6262,16 +6262,57 @@ SELECT regexp_match('abc01234xyz', '(?:(.*?)(\d+)(.*)){1,1}');
|
||||
<listitem>
|
||||
<para>
|
||||
<function>to_timestamp</function> and <function>to_date</function>
|
||||
skip multiple blank spaces in the input string unless the
|
||||
<literal>FX</literal> option is used. For example,
|
||||
<literal>to_timestamp('2000 JUN', 'YYYY MON')</literal> works, but
|
||||
skip multiple blank spaces at the beginning of the input string and
|
||||
around date and time values unless the <literal>FX</literal> option is used. For example,
|
||||
<literal>to_timestamp(' 2000 JUN', 'YYYY MON')</literal> and
|
||||
<literal>to_timestamp('2000 - JUN', 'YYYY-MON')</literal> work, but
|
||||
<literal>to_timestamp('2000 JUN', 'FXYYYY MON')</literal> returns an error
|
||||
because <function>to_timestamp</function> expects one space only.
|
||||
because <function>to_timestamp</function> expects a single space only.
|
||||
<literal>FX</literal> must be specified as the first item in
|
||||
the template.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
A separator (a space or a non-letter/non-digit character) in the template string of
|
||||
<function>to_timestamp</function> and <function>to_date</function>
|
||||
matches any single separator in the input string or is skipped,
|
||||
unless the <literal>FX</literal> option is used.
|
||||
For example, <literal>to_timestamp('2000JUN', 'YYYY///MON')</literal> and
|
||||
<literal>to_timestamp('2000/JUN', 'YYYY MON')</literal> work, but
|
||||
<literal>to_timestamp('2000//JUN', 'YYYY/MON')</literal>
|
||||
returns an error because the number of separators in the input string
|
||||
exceeds the number of separators in the template.
|
||||
</para>
|
||||
<para>
|
||||
If <literal>FX</literal> is specified, separator in template string
|
||||
matches to exactly one character in input string. Notice we don't insist
|
||||
input string character to be the same as template string separator.
|
||||
For example, <literal>to_timestamp('2000/JUN', 'FXYYYY MON')</literal>
|
||||
works, but <literal>to_timestamp('2000/JUN', 'FXYYYY MON')</literal>
|
||||
returns an error because a space second template string space consumed
|
||||
letter <literal>J</literal> from the input string.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<literal>TZH</literal> template pattern can match a signed number.
|
||||
Without the <literal>FX</literal> option, it may lead to ambiguity in
|
||||
interpretation of the minus sign, which can also be interpreted as a separator.
|
||||
This ambiguity is resolved as follows. If the number of separators before
|
||||
<literal>TZH</literal> in the template string is less than the number of
|
||||
separators before the minus sign in the input string, the minus sign
|
||||
is interpreted as part of <literal>TZH</literal>.
|
||||
Otherwise, the minus sign is considered to be a separator between values.
|
||||
For example, <literal>to_timestamp('2000 -10', 'YYYY TZH')</literal> matches
|
||||
<literal>-10</literal> to <literal>TZH</literal>, but
|
||||
<literal>to_timestamp('2000 -10', 'YYYY TZH')</literal>
|
||||
matches <literal>10</literal> to <literal>TZH</literal>.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Ordinary text is allowed in <function>to_char</function>
|
||||
@ -6287,6 +6328,19 @@ SELECT regexp_match('abc01234xyz', '(?:(.*?)(\d+)(.*)){1,1}');
|
||||
string; for example <literal>"XX"</literal> skips two input characters
|
||||
(whether or not they are <literal>XX</literal>).
|
||||
</para>
|
||||
<tip>
|
||||
<para>
|
||||
Prior to <productname>PostgreSQL</productname> 12, it was possible to
|
||||
skip arbitrary text in the input string using non-letter or non-digit
|
||||
characters. For example,
|
||||
<literal>to_timestamp('2000y6m1d', 'yyyy-MM-DD')</literal> used to
|
||||
work. Now you can only use letter characters for this purpose. For example,
|
||||
<literal>to_timestamp('2000y6m1d', 'yyyytMMtDDt')</literal> and
|
||||
<literal>to_timestamp('2000y6m1d', 'yyyy"y"MM"m"DD"d"')</literal>
|
||||
skip <literal>y</literal>, <literal>m</literal>, and
|
||||
<literal>d</literal>.
|
||||
</para>
|
||||
</tip>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
|
Reference in New Issue
Block a user