Support for FF1-FF6 datetime format patterns
SQL Standard 2016 defines FF1-FF9 format patters for fractions of seconds in jsonpath .datetime() method and CAST (... FORMAT ...) SQL clause. Parsing engine of upcoming .datetime() method will be shared with to_date()/ to_timestamp(). This patch implements FF1-FF6 format patterns for upcoming jsonpath .datetime() method. to_date()/to_timestamp() functions will also get support of this format patterns as positive side effect. FF7-FF9 are not supported due to lack of precision in our internal timestamp representation. Extracted from original patch by Nikita Glukhov, Teodor Sigaev, Oleg Bartunov. Heavily revised by me. Discussion: https://postgr.es/m/fcc6fc6a-b497-f39a-923d-aa34d0c588e8%402ndQuadrant.com Discussion: https://postgr.es/m/CAPpHfdsZgYEra_PeCLGNoXOWYx6iU-S3wF8aX0ObQUcZU%2B4XTw%40mail.gmail.com Author: Nikita Glukhov, Teodor Sigaev, Oleg Bartunov, Alexander Korotkov Reviewed-by: Anastasia Lubennikova, Peter Eisentraut
This commit is contained in:
parent
d812257809
commit
d589f94460
@ -6150,6 +6150,30 @@ SELECT regexp_match('abc01234xyz', '(?:(.*?)(\d+)(.*)){1,1}');
|
||||
<entry><literal>US</literal></entry>
|
||||
<entry>microsecond (000000-999999)</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>FF1</literal></entry>
|
||||
<entry>tenth of second (0-9)</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>FF2</literal></entry>
|
||||
<entry>hundredth of second (00-99)</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>FF3</literal></entry>
|
||||
<entry>millisecond (000-999)</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>FF4</literal></entry>
|
||||
<entry>tenth of a millisecond (0000-9999)</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>FF5</literal></entry>
|
||||
<entry>hundredth of a millisecond (00000-99999)</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>FF6</literal></entry>
|
||||
<entry>microsecond (000000-999999)</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>SSSS</literal></entry>
|
||||
<entry>seconds past midnight (0-86399)</entry>
|
||||
|
@ -86,6 +86,7 @@
|
||||
#endif
|
||||
|
||||
#include "catalog/pg_collation.h"
|
||||
#include "catalog/pg_type.h"
|
||||
#include "mb/pg_wchar.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/date.h"
|
||||
@ -434,7 +435,8 @@ typedef struct
|
||||
clock, /* 12 or 24 hour clock? */
|
||||
tzsign, /* +1, -1 or 0 if timezone info is absent */
|
||||
tzh,
|
||||
tzm;
|
||||
tzm,
|
||||
ff; /* fractional precision */
|
||||
} TmFromChar;
|
||||
|
||||
#define ZERO_tmfc(_X) memset(_X, 0, sizeof(TmFromChar))
|
||||
@ -594,6 +596,12 @@ typedef enum
|
||||
DCH_Day,
|
||||
DCH_Dy,
|
||||
DCH_D,
|
||||
DCH_FF1,
|
||||
DCH_FF2,
|
||||
DCH_FF3,
|
||||
DCH_FF4,
|
||||
DCH_FF5,
|
||||
DCH_FF6,
|
||||
DCH_FX, /* global suffix */
|
||||
DCH_HH24,
|
||||
DCH_HH12,
|
||||
@ -643,6 +651,12 @@ typedef enum
|
||||
DCH_dd,
|
||||
DCH_dy,
|
||||
DCH_d,
|
||||
DCH_ff1,
|
||||
DCH_ff2,
|
||||
DCH_ff3,
|
||||
DCH_ff4,
|
||||
DCH_ff5,
|
||||
DCH_ff6,
|
||||
DCH_fx,
|
||||
DCH_hh24,
|
||||
DCH_hh12,
|
||||
@ -743,7 +757,13 @@ static const KeyWord DCH_keywords[] = {
|
||||
{"Day", 3, DCH_Day, false, FROM_CHAR_DATE_NONE},
|
||||
{"Dy", 2, DCH_Dy, false, FROM_CHAR_DATE_NONE},
|
||||
{"D", 1, DCH_D, true, FROM_CHAR_DATE_GREGORIAN},
|
||||
{"FX", 2, DCH_FX, false, FROM_CHAR_DATE_NONE}, /* F */
|
||||
{"FF1", 3, DCH_FF1, false, FROM_CHAR_DATE_NONE}, /* F */
|
||||
{"FF2", 3, DCH_FF2, false, FROM_CHAR_DATE_NONE},
|
||||
{"FF3", 3, DCH_FF3, false, FROM_CHAR_DATE_NONE},
|
||||
{"FF4", 3, DCH_FF4, false, FROM_CHAR_DATE_NONE},
|
||||
{"FF5", 3, DCH_FF5, false, FROM_CHAR_DATE_NONE},
|
||||
{"FF6", 3, DCH_FF6, false, FROM_CHAR_DATE_NONE},
|
||||
{"FX", 2, DCH_FX, false, FROM_CHAR_DATE_NONE},
|
||||
{"HH24", 4, DCH_HH24, true, FROM_CHAR_DATE_NONE}, /* H */
|
||||
{"HH12", 4, DCH_HH12, true, FROM_CHAR_DATE_NONE},
|
||||
{"HH", 2, DCH_HH, true, FROM_CHAR_DATE_NONE},
|
||||
@ -792,7 +812,13 @@ static const KeyWord DCH_keywords[] = {
|
||||
{"dd", 2, DCH_DD, true, FROM_CHAR_DATE_GREGORIAN},
|
||||
{"dy", 2, DCH_dy, false, FROM_CHAR_DATE_NONE},
|
||||
{"d", 1, DCH_D, true, FROM_CHAR_DATE_GREGORIAN},
|
||||
{"fx", 2, DCH_FX, false, FROM_CHAR_DATE_NONE}, /* f */
|
||||
{"ff1", 3, DCH_FF1, false, FROM_CHAR_DATE_NONE}, /* f */
|
||||
{"ff2", 3, DCH_FF2, false, FROM_CHAR_DATE_NONE},
|
||||
{"ff3", 3, DCH_FF3, false, FROM_CHAR_DATE_NONE},
|
||||
{"ff4", 3, DCH_FF4, false, FROM_CHAR_DATE_NONE},
|
||||
{"ff5", 3, DCH_FF5, false, FROM_CHAR_DATE_NONE},
|
||||
{"ff6", 3, DCH_FF6, false, FROM_CHAR_DATE_NONE},
|
||||
{"fx", 2, DCH_FX, false, FROM_CHAR_DATE_NONE},
|
||||
{"hh24", 4, DCH_HH24, true, FROM_CHAR_DATE_NONE}, /* h */
|
||||
{"hh12", 4, DCH_HH12, true, FROM_CHAR_DATE_NONE},
|
||||
{"hh", 2, DCH_HH, true, FROM_CHAR_DATE_NONE},
|
||||
@ -893,10 +919,10 @@ static const int DCH_index[KeyWord_INDEX_SIZE] = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
||||
-1, -1, -1, -1, -1, DCH_A_D, DCH_B_C, DCH_CC, DCH_DAY, -1,
|
||||
DCH_FX, -1, DCH_HH24, DCH_IDDD, DCH_J, -1, -1, DCH_MI, -1, DCH_OF,
|
||||
DCH_FF1, -1, DCH_HH24, DCH_IDDD, DCH_J, -1, -1, DCH_MI, -1, DCH_OF,
|
||||
DCH_P_M, DCH_Q, DCH_RM, DCH_SSSS, DCH_TZH, DCH_US, -1, DCH_WW, -1, DCH_Y_YYY,
|
||||
-1, -1, -1, -1, -1, -1, -1, DCH_a_d, DCH_b_c, DCH_cc,
|
||||
DCH_day, -1, DCH_fx, -1, DCH_hh24, DCH_iddd, DCH_j, -1, -1, DCH_mi,
|
||||
DCH_day, -1, DCH_ff1, -1, DCH_hh24, DCH_iddd, DCH_j, -1, -1, DCH_mi,
|
||||
-1, -1, DCH_p_m, DCH_q, DCH_rm, DCH_ssss, DCH_tz, DCH_us, -1, DCH_ww,
|
||||
-1, DCH_y_yyy, -1, -1, -1, -1
|
||||
|
||||
@ -960,7 +986,6 @@ typedef struct NUMProc
|
||||
*L_currency_symbol;
|
||||
} NUMProc;
|
||||
|
||||
|
||||
/* ----------
|
||||
* Functions
|
||||
* ----------
|
||||
@ -993,7 +1018,7 @@ static int from_char_parse_int(int *dest, char **src, FormatNode *node);
|
||||
static int seq_search(char *name, const char *const *array, int type, int max, int *len);
|
||||
static int from_char_seq_search(int *dest, char **src, const char *const *array, int type, int max, FormatNode *node);
|
||||
static void do_to_timestamp(text *date_txt, text *fmt,
|
||||
struct pg_tm *tm, fsec_t *fsec);
|
||||
struct pg_tm *tm, fsec_t *fsec, int *fprec);
|
||||
static char *fill_str(char *str, int c, int max);
|
||||
static FormatNode *NUM_cache(int len, NUMDesc *Num, text *pars_str, bool *shouldFree);
|
||||
static char *int_to_roman(int number);
|
||||
@ -2518,18 +2543,32 @@ DCH_to_char(FormatNode *node, bool is_interval, TmToChar *in, char *out, Oid col
|
||||
str_numth(s, s, S_TH_TYPE(n->suffix));
|
||||
s += strlen(s);
|
||||
break;
|
||||
#define DCH_to_char_fsec(frac_fmt, frac_val) \
|
||||
sprintf(s, frac_fmt, (int) (frac_val)); \
|
||||
if (S_THth(n->suffix)) \
|
||||
str_numth(s, s, S_TH_TYPE(n->suffix)); \
|
||||
s += strlen(s);
|
||||
case DCH_FF1: /* tenth of second */
|
||||
DCH_to_char_fsec("%01d", in->fsec / 100000);
|
||||
break;
|
||||
case DCH_FF2: /* hundredth of second */
|
||||
DCH_to_char_fsec("%02d", in->fsec / 10000);
|
||||
break;
|
||||
case DCH_FF3:
|
||||
case DCH_MS: /* millisecond */
|
||||
sprintf(s, "%03d", (int) (in->fsec / INT64CONST(1000)));
|
||||
if (S_THth(n->suffix))
|
||||
str_numth(s, s, S_TH_TYPE(n->suffix));
|
||||
s += strlen(s);
|
||||
DCH_to_char_fsec("%03d", in->fsec / 1000);
|
||||
break;
|
||||
case DCH_FF4: /* tenth of a millisecond */
|
||||
DCH_to_char_fsec("%04d", in->fsec / 100);
|
||||
break;
|
||||
case DCH_FF5: /* hundredth of a millisecond */
|
||||
DCH_to_char_fsec("%05d", in->fsec / 10);
|
||||
break;
|
||||
case DCH_FF6:
|
||||
case DCH_US: /* microsecond */
|
||||
sprintf(s, "%06d", (int) in->fsec);
|
||||
if (S_THth(n->suffix))
|
||||
str_numth(s, s, S_TH_TYPE(n->suffix));
|
||||
s += strlen(s);
|
||||
DCH_to_char_fsec("%06d", in->fsec);
|
||||
break;
|
||||
#undef DCH_to_char_fsec
|
||||
case DCH_SSSS:
|
||||
sprintf(s, "%d", tm->tm_hour * SECS_PER_HOUR +
|
||||
tm->tm_min * SECS_PER_MINUTE +
|
||||
@ -3154,8 +3193,18 @@ DCH_from_char(FormatNode *node, char *in, TmFromChar *out)
|
||||
|
||||
SKIP_THth(s, n->suffix);
|
||||
break;
|
||||
case DCH_FF1:
|
||||
case DCH_FF2:
|
||||
case DCH_FF3:
|
||||
case DCH_FF4:
|
||||
case DCH_FF5:
|
||||
case DCH_FF6:
|
||||
out->ff = n->key->id - DCH_FF1 + 1;
|
||||
/* fall through */
|
||||
case DCH_US: /* microsecond */
|
||||
len = from_char_parse_int_len(&out->us, &s, 6, n);
|
||||
len = from_char_parse_int_len(&out->us, &s,
|
||||
n->key->id == DCH_US ? 6 :
|
||||
out->ff, n);
|
||||
|
||||
out->us *= len == 1 ? 100000 :
|
||||
len == 2 ? 10000 :
|
||||
@ -3689,8 +3738,9 @@ to_timestamp(PG_FUNCTION_ARGS)
|
||||
int tz;
|
||||
struct pg_tm tm;
|
||||
fsec_t fsec;
|
||||
int fprec;
|
||||
|
||||
do_to_timestamp(date_txt, fmt, &tm, &fsec);
|
||||
do_to_timestamp(date_txt, fmt, &tm, &fsec, &fprec);
|
||||
|
||||
/* Use the specified time zone, if any. */
|
||||
if (tm.tm_zone)
|
||||
@ -3708,6 +3758,10 @@ to_timestamp(PG_FUNCTION_ARGS)
|
||||
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
|
||||
errmsg("timestamp out of range")));
|
||||
|
||||
/* Use the specified fractional precision, if any. */
|
||||
if (fprec)
|
||||
AdjustTimestampForTypmod(&result, fprec);
|
||||
|
||||
PG_RETURN_TIMESTAMP(result);
|
||||
}
|
||||
|
||||
@ -3725,7 +3779,7 @@ to_date(PG_FUNCTION_ARGS)
|
||||
struct pg_tm tm;
|
||||
fsec_t fsec;
|
||||
|
||||
do_to_timestamp(date_txt, fmt, &tm, &fsec);
|
||||
do_to_timestamp(date_txt, fmt, &tm, &fsec, NULL);
|
||||
|
||||
/* Prevent overflow in Julian-day routines */
|
||||
if (!IS_VALID_JULIAN(tm.tm_year, tm.tm_mon, tm.tm_mday))
|
||||
@ -3749,8 +3803,8 @@ to_date(PG_FUNCTION_ARGS)
|
||||
/*
|
||||
* do_to_timestamp: shared code for to_timestamp and to_date
|
||||
*
|
||||
* Parse the 'date_txt' according to 'fmt', return results as a struct pg_tm
|
||||
* and fractional seconds.
|
||||
* Parse the 'date_txt' according to 'fmt', return results as a struct pg_tm,
|
||||
* fractional seconds, and fractional precision.
|
||||
*
|
||||
* We parse 'fmt' into a list of FormatNodes, which is then passed to
|
||||
* DCH_from_char to populate a TmFromChar with the parsed contents of
|
||||
@ -3761,7 +3815,7 @@ to_date(PG_FUNCTION_ARGS)
|
||||
*/
|
||||
static void
|
||||
do_to_timestamp(text *date_txt, text *fmt,
|
||||
struct pg_tm *tm, fsec_t *fsec)
|
||||
struct pg_tm *tm, fsec_t *fsec, int *fprec)
|
||||
{
|
||||
FormatNode *format;
|
||||
TmFromChar tmfc;
|
||||
@ -3817,6 +3871,7 @@ do_to_timestamp(text *date_txt, text *fmt,
|
||||
DCH_from_char(format, date_str, &tmfc);
|
||||
|
||||
pfree(fmt_str);
|
||||
|
||||
if (!incache)
|
||||
pfree(format);
|
||||
}
|
||||
@ -3998,6 +4053,8 @@ do_to_timestamp(text *date_txt, text *fmt,
|
||||
*fsec += tmfc.ms * 1000;
|
||||
if (tmfc.us)
|
||||
*fsec += tmfc.us;
|
||||
if (fprec)
|
||||
*fprec = tmfc.ff; /* fractional precision, if specified */
|
||||
|
||||
/* Range-check date fields according to bit mask computed above */
|
||||
if (fmask != 0)
|
||||
|
@ -70,7 +70,6 @@ typedef struct
|
||||
|
||||
static TimeOffset time2t(const int hour, const int min, const int sec, const fsec_t fsec);
|
||||
static Timestamp dt2local(Timestamp dt, int timezone);
|
||||
static void AdjustTimestampForTypmod(Timestamp *time, int32 typmod);
|
||||
static void AdjustIntervalForTypmod(Interval *interval, int32 typmod);
|
||||
static TimestampTz timestamp2timestamptz(Timestamp timestamp);
|
||||
static Timestamp timestamptz2timestamp(TimestampTz timestamp);
|
||||
@ -333,7 +332,7 @@ timestamp_scale(PG_FUNCTION_ARGS)
|
||||
* AdjustTimestampForTypmod --- round off a timestamp to suit given typmod
|
||||
* Works for either timestamp or timestamptz.
|
||||
*/
|
||||
static void
|
||||
void
|
||||
AdjustTimestampForTypmod(Timestamp *time, int32 typmod)
|
||||
{
|
||||
static const int64 TimestampScales[MAX_TIMESTAMP_PRECISION + 1] = {
|
||||
|
@ -336,4 +336,6 @@ extern TimeZoneAbbrevTable *ConvertTimeZoneAbbrevs(struct tzEntry *abbrevs,
|
||||
int n);
|
||||
extern void InstallTimeZoneAbbrevs(TimeZoneAbbrevTable *tbl);
|
||||
|
||||
extern void AdjustTimestampForTypmod(Timestamp *time, int32 typmod);
|
||||
|
||||
#endif /* DATETIME_H */
|
||||
|
@ -2786,6 +2786,85 @@ SELECT to_timestamp('2011-12-18 11:38 20', 'YYYY-MM-DD HH12:MI TZM');
|
||||
Sun Dec 18 03:18:00 2011 PST
|
||||
(1 row)
|
||||
|
||||
SELECT i, to_timestamp('2018-11-02 12:34:56', 'YYYY-MM-DD HH24:MI:SS.FF' || i) FROM generate_series(1, 6) i;
|
||||
i | to_timestamp
|
||||
---+------------------------------
|
||||
1 | Fri Nov 02 12:34:56 2018 PDT
|
||||
2 | Fri Nov 02 12:34:56 2018 PDT
|
||||
3 | Fri Nov 02 12:34:56 2018 PDT
|
||||
4 | Fri Nov 02 12:34:56 2018 PDT
|
||||
5 | Fri Nov 02 12:34:56 2018 PDT
|
||||
6 | Fri Nov 02 12:34:56 2018 PDT
|
||||
(6 rows)
|
||||
|
||||
SELECT i, to_timestamp('2018-11-02 12:34:56.1', 'YYYY-MM-DD HH24:MI:SS.FF' || i) FROM generate_series(1, 6) i;
|
||||
i | to_timestamp
|
||||
---+--------------------------------
|
||||
1 | Fri Nov 02 12:34:56.1 2018 PDT
|
||||
2 | Fri Nov 02 12:34:56.1 2018 PDT
|
||||
3 | Fri Nov 02 12:34:56.1 2018 PDT
|
||||
4 | Fri Nov 02 12:34:56.1 2018 PDT
|
||||
5 | Fri Nov 02 12:34:56.1 2018 PDT
|
||||
6 | Fri Nov 02 12:34:56.1 2018 PDT
|
||||
(6 rows)
|
||||
|
||||
SELECT i, to_timestamp('2018-11-02 12:34:56.12', 'YYYY-MM-DD HH24:MI:SS.FF' || i) FROM generate_series(1, 6) i;
|
||||
i | to_timestamp
|
||||
---+---------------------------------
|
||||
1 | Fri Nov 02 12:34:56.1 2018 PDT
|
||||
2 | Fri Nov 02 12:34:56.12 2018 PDT
|
||||
3 | Fri Nov 02 12:34:56.12 2018 PDT
|
||||
4 | Fri Nov 02 12:34:56.12 2018 PDT
|
||||
5 | Fri Nov 02 12:34:56.12 2018 PDT
|
||||
6 | Fri Nov 02 12:34:56.12 2018 PDT
|
||||
(6 rows)
|
||||
|
||||
SELECT i, to_timestamp('2018-11-02 12:34:56.123', 'YYYY-MM-DD HH24:MI:SS.FF' || i) FROM generate_series(1, 6) i;
|
||||
i | to_timestamp
|
||||
---+----------------------------------
|
||||
1 | Fri Nov 02 12:34:56.1 2018 PDT
|
||||
2 | Fri Nov 02 12:34:56.12 2018 PDT
|
||||
3 | Fri Nov 02 12:34:56.123 2018 PDT
|
||||
4 | Fri Nov 02 12:34:56.123 2018 PDT
|
||||
5 | Fri Nov 02 12:34:56.123 2018 PDT
|
||||
6 | Fri Nov 02 12:34:56.123 2018 PDT
|
||||
(6 rows)
|
||||
|
||||
SELECT i, to_timestamp('2018-11-02 12:34:56.1234', 'YYYY-MM-DD HH24:MI:SS.FF' || i) FROM generate_series(1, 6) i;
|
||||
i | to_timestamp
|
||||
---+-----------------------------------
|
||||
1 | Fri Nov 02 12:34:56.1 2018 PDT
|
||||
2 | Fri Nov 02 12:34:56.12 2018 PDT
|
||||
3 | Fri Nov 02 12:34:56.123 2018 PDT
|
||||
4 | Fri Nov 02 12:34:56.1234 2018 PDT
|
||||
5 | Fri Nov 02 12:34:56.1234 2018 PDT
|
||||
6 | Fri Nov 02 12:34:56.1234 2018 PDT
|
||||
(6 rows)
|
||||
|
||||
SELECT i, to_timestamp('2018-11-02 12:34:56.12345', 'YYYY-MM-DD HH24:MI:SS.FF' || i) FROM generate_series(1, 6) i;
|
||||
i | to_timestamp
|
||||
---+------------------------------------
|
||||
1 | Fri Nov 02 12:34:56.1 2018 PDT
|
||||
2 | Fri Nov 02 12:34:56.12 2018 PDT
|
||||
3 | Fri Nov 02 12:34:56.123 2018 PDT
|
||||
4 | Fri Nov 02 12:34:56.1235 2018 PDT
|
||||
5 | Fri Nov 02 12:34:56.12345 2018 PDT
|
||||
6 | Fri Nov 02 12:34:56.12345 2018 PDT
|
||||
(6 rows)
|
||||
|
||||
SELECT i, to_timestamp('2018-11-02 12:34:56.123456', 'YYYY-MM-DD HH24:MI:SS.FF' || i) FROM generate_series(1, 6) i;
|
||||
i | to_timestamp
|
||||
---+-------------------------------------
|
||||
1 | Fri Nov 02 12:34:56.1 2018 PDT
|
||||
2 | Fri Nov 02 12:34:56.12 2018 PDT
|
||||
3 | Fri Nov 02 12:34:56.123 2018 PDT
|
||||
4 | Fri Nov 02 12:34:56.1235 2018 PDT
|
||||
5 | Fri Nov 02 12:34:56.12346 2018 PDT
|
||||
6 | Fri Nov 02 12:34:56.123456 2018 PDT
|
||||
(6 rows)
|
||||
|
||||
SELECT i, to_timestamp('2018-11-02 12:34:56.123456789', 'YYYY-MM-DD HH24:MI:SS.FF' || i) FROM generate_series(1, 6) i;
|
||||
ERROR: date/time field value out of range: "2018-11-02 12:34:56.123456789"
|
||||
--
|
||||
-- Check handling of multiple spaces in format and/or input
|
||||
--
|
||||
|
@ -1584,6 +1584,21 @@ SELECT '' AS to_char_11, to_char(d1, 'FMIYYY FMIYY FMIY FMI FMIW FMIDDD FMID')
|
||||
| 2001 1 1 1 1 1 1
|
||||
(65 rows)
|
||||
|
||||
SELECT '' AS to_char_12, to_char(d, 'FF1 FF2 FF3 FF4 FF5 FF6 ff1 ff2 ff3 ff4 ff5 ff6 MS US')
|
||||
FROM (VALUES
|
||||
('2018-11-02 12:34:56'::timestamp),
|
||||
('2018-11-02 12:34:56.78'),
|
||||
('2018-11-02 12:34:56.78901'),
|
||||
('2018-11-02 12:34:56.78901234')
|
||||
) d(d);
|
||||
to_char_12 | to_char
|
||||
------------+--------------------------------------------------------------------
|
||||
| 0 00 000 0000 00000 000000 0 00 000 0000 00000 000000 000 000000
|
||||
| 7 78 780 7800 78000 780000 7 78 780 7800 78000 780000 780 780000
|
||||
| 7 78 789 7890 78901 789010 7 78 789 7890 78901 789010 789 789010
|
||||
| 7 78 789 7890 78901 789012 7 78 789 7890 78901 789012 789 789012
|
||||
(4 rows)
|
||||
|
||||
-- timestamp numeric fields constructor
|
||||
SELECT make_timestamp(2014,12,28,6,30,45.887);
|
||||
make_timestamp
|
||||
|
@ -1704,6 +1704,21 @@ SELECT '' AS to_char_11, to_char(d1, 'FMIYYY FMIYY FMIY FMI FMIW FMIDDD FMID')
|
||||
| 2001 1 1 1 1 1 1
|
||||
(66 rows)
|
||||
|
||||
SELECT '' AS to_char_12, to_char(d, 'FF1 FF2 FF3 FF4 FF5 FF6 ff1 ff2 ff3 ff4 ff5 ff6 MS US')
|
||||
FROM (VALUES
|
||||
('2018-11-02 12:34:56'::timestamptz),
|
||||
('2018-11-02 12:34:56.78'),
|
||||
('2018-11-02 12:34:56.78901'),
|
||||
('2018-11-02 12:34:56.78901234')
|
||||
) d(d);
|
||||
to_char_12 | to_char
|
||||
------------+--------------------------------------------------------------------
|
||||
| 0 00 000 0000 00000 000000 0 00 000 0000 00000 000000 000 000000
|
||||
| 7 78 780 7800 78000 780000 7 78 780 7800 78000 780000 780 780000
|
||||
| 7 78 789 7890 78901 789010 7 78 789 7890 78901 789010 789 789010
|
||||
| 7 78 789 7890 78901 789012 7 78 789 7890 78901 789012 789 789012
|
||||
(4 rows)
|
||||
|
||||
-- Check OF, TZH, TZM with various zone offsets, particularly fractional hours
|
||||
SET timezone = '00:00';
|
||||
SELECT to_char(now(), 'OF') as "OF", to_char(now(), 'TZH:TZM') as "TZH:TZM";
|
||||
|
@ -402,6 +402,15 @@ SELECT to_timestamp('2011-12-18 11:38 +05:20', 'YYYY-MM-DD HH12:MI TZH:TZM');
|
||||
SELECT to_timestamp('2011-12-18 11:38 -05:20', 'YYYY-MM-DD HH12:MI TZH:TZM');
|
||||
SELECT to_timestamp('2011-12-18 11:38 20', 'YYYY-MM-DD HH12:MI TZM');
|
||||
|
||||
SELECT i, to_timestamp('2018-11-02 12:34:56', 'YYYY-MM-DD HH24:MI:SS.FF' || i) FROM generate_series(1, 6) i;
|
||||
SELECT i, to_timestamp('2018-11-02 12:34:56.1', 'YYYY-MM-DD HH24:MI:SS.FF' || i) FROM generate_series(1, 6) i;
|
||||
SELECT i, to_timestamp('2018-11-02 12:34:56.12', 'YYYY-MM-DD HH24:MI:SS.FF' || i) FROM generate_series(1, 6) i;
|
||||
SELECT i, to_timestamp('2018-11-02 12:34:56.123', 'YYYY-MM-DD HH24:MI:SS.FF' || i) FROM generate_series(1, 6) i;
|
||||
SELECT i, to_timestamp('2018-11-02 12:34:56.1234', 'YYYY-MM-DD HH24:MI:SS.FF' || i) FROM generate_series(1, 6) i;
|
||||
SELECT i, to_timestamp('2018-11-02 12:34:56.12345', 'YYYY-MM-DD HH24:MI:SS.FF' || i) FROM generate_series(1, 6) i;
|
||||
SELECT i, to_timestamp('2018-11-02 12:34:56.123456', 'YYYY-MM-DD HH24:MI:SS.FF' || i) FROM generate_series(1, 6) i;
|
||||
SELECT i, to_timestamp('2018-11-02 12:34:56.123456789', 'YYYY-MM-DD HH24:MI:SS.FF' || i) FROM generate_series(1, 6) i;
|
||||
|
||||
--
|
||||
-- Check handling of multiple spaces in format and/or input
|
||||
--
|
||||
|
@ -224,5 +224,13 @@ SELECT '' AS to_char_10, to_char(d1, 'IYYY IYY IY I IW IDDD ID')
|
||||
SELECT '' AS to_char_11, to_char(d1, 'FMIYYY FMIYY FMIY FMI FMIW FMIDDD FMID')
|
||||
FROM TIMESTAMP_TBL;
|
||||
|
||||
SELECT '' AS to_char_12, to_char(d, 'FF1 FF2 FF3 FF4 FF5 FF6 ff1 ff2 ff3 ff4 ff5 ff6 MS US')
|
||||
FROM (VALUES
|
||||
('2018-11-02 12:34:56'::timestamp),
|
||||
('2018-11-02 12:34:56.78'),
|
||||
('2018-11-02 12:34:56.78901'),
|
||||
('2018-11-02 12:34:56.78901234')
|
||||
) d(d);
|
||||
|
||||
-- timestamp numeric fields constructor
|
||||
SELECT make_timestamp(2014,12,28,6,30,45.887);
|
||||
|
@ -248,6 +248,14 @@ SELECT '' AS to_char_10, to_char(d1, 'IYYY IYY IY I IW IDDD ID')
|
||||
SELECT '' AS to_char_11, to_char(d1, 'FMIYYY FMIYY FMIY FMI FMIW FMIDDD FMID')
|
||||
FROM TIMESTAMPTZ_TBL;
|
||||
|
||||
SELECT '' AS to_char_12, to_char(d, 'FF1 FF2 FF3 FF4 FF5 FF6 ff1 ff2 ff3 ff4 ff5 ff6 MS US')
|
||||
FROM (VALUES
|
||||
('2018-11-02 12:34:56'::timestamptz),
|
||||
('2018-11-02 12:34:56.78'),
|
||||
('2018-11-02 12:34:56.78901'),
|
||||
('2018-11-02 12:34:56.78901234')
|
||||
) d(d);
|
||||
|
||||
-- Check OF, TZH, TZM with various zone offsets, particularly fractional hours
|
||||
SET timezone = '00:00';
|
||||
SELECT to_char(now(), 'OF') as "OF", to_char(now(), 'TZH:TZM') as "TZH:TZM";
|
||||
|
Loading…
x
Reference in New Issue
Block a user