Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
e2252604
Commit
e2252604
authored
Jul 01, 2000
by
Bruce Momjian
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Back out Karels to_char changes.
parent
b150906b
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
407 additions
and
462 deletions
+407
-462
doc/src/sgml/func.sgml
doc/src/sgml/func.sgml
+5
-8
src/backend/utils/adt/formatting.c
src/backend/utils/adt/formatting.c
+370
-422
src/test/regress/expected/timestamp.out
src/test/regress/expected/timestamp.out
+32
-32
No files found.
doc/src/sgml/func.sgml
View file @
e2252604
...
...
@@ -785,11 +785,11 @@
</row>
<row>
<entry>W</entry>
<entry>week of month
(1-5) where first week start on the first day of the month
</entry>
<entry>week of month</entry>
</row>
<row>
<entry>WW</entry>
<entry>week number of year
(1-53) where first week start on the first day of the year
</entry>
<entry>week number of year</entry>
</row>
<row>
<entry>CC</entry>
...
...
@@ -871,12 +871,9 @@
<listitem>
<para>
<function>to_timestamp</function> and <function>to_date</function>
skip multiple blank space in converted string if the <literal>FX</literal> option
is not used. <literal>FX</literal> must be specified as the first item
in the template; for example
<literal>to_timestamp('2000 JUN','YYYY MON')</literal> is right, but
<literal>to_timestamp('2000 JUN','FXYYYY MON')</literal> returns error,
because to_timestamp() expects one blank space only.
skip blank space if the <literal>FX</literal> option is
not used. <literal>FX</literal> must be specified as the first item
in the template.
</para>
</listitem>
...
...
src/backend/utils/adt/formatting.c
View file @
e2252604
/* -----------------------------------------------------------------------
* formatting.c
*
* $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.1
5 2000/07/01 14:10:29
momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.1
6 2000/07/01 21:27:11
momjian Exp $
*
*
* Portions Copyright (c) 1999-2000, PostgreSQL, Inc
...
...
@@ -68,8 +67,11 @@
#include "postgres.h"
#include "utils/builtins.h"
#include "utils/pg_locale.h"
#include "utils/date.h"
#include "utils/datetime.h"
#include "utils/formatting.h"
#include "utils/int8.h"
#include "utils/pg_locale.h"
/* ----------
* Routines type
...
...
@@ -232,6 +234,14 @@ static char *numth[] = {"st", "nd", "rd", "th", NULL};
#define TH_LOWER 2
#ifdef DEBUG_TO_FROM_CHAR
#define NOTICE_TM {\
elog(DEBUG_elog_output, "TM:\nsec %d\nyear %d\nmin %d\nwday %d\nhour %d\nyday %d\nmday %d\nnisdst %d\nmon %d\n",\
tm->tm_sec, tm->tm_year,\
tm->tm_min, tm->tm_wday, tm->tm_hour, tm->tm_yday,\
tm->tm_mday, tm->tm_isdst,tm->tm_mon);\
}
#endif
/* ----------
* Flags for DCH version
...
...
@@ -337,50 +347,12 @@ static int NUMCounter = 0;
#define MAX_INT32 (2147483640)
/* ----------
* For char->date/time conversion
* ----------
*/
typedef
struct
{
int
hh
,
am
,
pm
,
mi
,
ss
,
ssss
,
d
,
dd
,
ddd
,
mm
,
yyyy
,
bc
,
ww
,
w
,
cc
,
q
,
j
;
}
TmFromChar
;
#define ZERO_tmfc( _X ) \
do { \
(_X)->hh= (_X)->am= (_X)->pm= (_X)->mi= (_X)->ss= (_X)->ssss= \
(_X)->d= (_X)->dd= (_X)->ddd= (_X)->mm= (_X)->yyyy= (_X)->bc= \
(_X)->ww= (_X)->w= (_X)->cc= (_X)->q= (_X)->j= 0; \
} while(0)
#ifdef DEBUG_TO_FROM_CHAR
#define NOTICE_TMFC \
elog(DEBUG_elog_output, "TMFC:\nhh %d\nam %d\npm %d\nmi %d\nss %d\nssss %d\nd %d\ndd %d\nddd %d\nmm %d\nyyyy %d\nbc %d\nww %d\nw %d\ncc %d\nq %d\nj %d", \
tmfc->hh, tmfc->am, tmfc->pm, tmfc->mi, tmfc->ss, \
tmfc->ssss, tmfc->d, tmfc->dd, tmfc->ddd, tmfc->mm, \
tmfc->yyyy, tmfc->bc, tmfc->ww, tmfc->w, tmfc->cc, \
tmfc->q, tmfc->j);
#define NOTICE_TM \
elog(DEBUG_elog_output, "TM:\nsec %d\nyear %d\nmin %d\nwday %d\nhour %d\nyday %d\nmday %d\nnisdst %d\nmon %d\n",\
tm->tm_sec, tm->tm_year,\
tm->tm_min, tm->tm_wday, tm->tm_hour, tm->tm_yday,\
tm->tm_mday, tm->tm_isdst,tm->tm_mon)
#endif
#define ZERO_tm( _X ) \
do { \
(_X)->tm_sec = (_X)->tm_year = (_X)->tm_min = (_X)->tm_wday = \
(_X)->tm_hour = (_X)->tm_yday = (_X)->tm_isdst = 0; \
(_X)->tm_mday = (_X)->tm_mon = 1; \
} while (0);
/* ----------
* Private global-modul definitions
* ----------
*/
static
struct
tm
_tm
,
*
tm
=
&
_tm
;
static
TmFromChar
_tmfc
,
*
tmfc
=
&
_tmfc
;
static
struct
tm
_tm
,
*
tm
=
&
_tm
;
/* ----------
* Utils
...
...
@@ -857,6 +829,7 @@ index_seq_search(char *str, KeyWord *kw, int *index)
if
((
poz
=
*
(
index
+
(
*
str
-
' '
)))
>
-
1
)
{
KeyWord
*
k
=
kw
+
poz
;
do
...
...
@@ -1190,6 +1163,7 @@ DCH_processor(FormatNode *node, char *inout, int flag)
{
if
(
n
->
type
==
NODE_TYPE_ACTION
)
{
int
len
;
/* ----------
...
...
@@ -1201,15 +1175,18 @@ DCH_processor(FormatNode *node, char *inout, int flag)
s
+=
len
;
else
if
(
len
==
-
1
)
continue
;
}
else
{
/* ----------
* Remove to output char from input in TO_CHAR
* ----------
*/
if
(
flag
==
TO_CHAR
)
*
s
=
n
->
character
;
else
{
/* ----------
...
...
@@ -1218,12 +1195,14 @@ DCH_processor(FormatNode *node, char *inout, int flag)
*/
if
(
isspace
(
n
->
character
)
&&
IS_FX
==
0
)
{
while
(
*
s
!=
'\0'
&&
isspace
(
*
(
s
+
1
)))
while
(
*
s
!=
'\0'
&&
isspace
(
(
int
)
*
(
s
+
1
)))
++
s
;
}
}
}
++
s
;
/* ! */
}
if
(
flag
==
TO_CHAR
)
...
...
@@ -1282,14 +1261,17 @@ static char *
get_th
(
char
*
num
,
int
type
)
{
int
len
=
strlen
(
num
),
last
;
last
,
seclast
;
last
=
*
(
num
+
(
len
-
1
));
if
(
!
isdigit
((
unsigned
char
)
last
))
elog
(
ERROR
,
"get_th: '%s' is not number."
,
num
);
/* 11 || 12 */
if
(
len
==
2
&&
(
last
==
'1'
||
last
==
'2'
)
&&
*
num
==
'1'
)
/*
* All "teens" (<x>1[0-9]) get 'TH/th',
* while <x>[02-9][123] still get 'ST/st', 'ND/nd', 'RD/rd', respectively
*/
if
((
len
>
1
)
&&
((
seclast
=
num
[
len
-
2
])
==
'1'
))
last
=
0
;
switch
(
last
)
...
...
@@ -1529,6 +1511,7 @@ dch_global(int arg, char *inout, int suf, int flag, FormatNode *node)
{
switch
(
arg
)
{
case
DCH_FX
:
DCH_global_flag
|=
DCH_F_FX
;
break
;
...
...
@@ -1536,8 +1519,6 @@ dch_global(int arg, char *inout, int suf, int flag, FormatNode *node)
return
-
1
;
}
#define AMPM_ERROR elog(ERROR, "to_timestamp(): bad AM/PM string")
/* ----------
* Master function of TIME for:
* TO_CHAR - write (inout) formated string
...
...
@@ -1551,82 +1532,67 @@ dch_time(int arg, char *inout, int suf, int flag, FormatNode *node)
switch
(
arg
)
{
case
DCH_A_M
:
case
DCH_P_M
:
if
(
flag
==
TO_CHAR
)
{
strcpy
(
inout
,
((
tm
->
tm_hour
>
11
&&
tm
->
tm_hour
<
24
)
?
P_M_STR
:
A_M_STR
));
strcpy
(
inout
,
(
tm
->
tm_hour
>
13
?
P_M_STR
:
A_M_STR
));
return
3
;
}
else
if
(
flag
==
FROM_CHAR
)
{
if
(
strncmp
(
inout
,
P_M_STR
,
4
)
==
0
)
tmfc
->
pm
=
TRUE
;
else
if
(
strncmp
(
inout
,
A_M_STR
,
4
)
==
0
)
tmfc
->
am
=
TRUE
;
else
AMPM_ERROR
;
if
(
strncmp
(
inout
,
P_M_STR
,
4
)
==
0
&&
tm
->
tm_hour
<
13
)
tm
->
tm_hour
+=
12
;
return
3
;
}
break
;
case
DCH_AM
:
case
DCH_PM
:
if
(
flag
==
TO_CHAR
)
{
strcpy
(
inout
,
((
tm
->
tm_hour
>
11
&&
tm
->
tm_hour
<
24
)
?
PM_STR
:
AM_STR
));
strcpy
(
inout
,
(
tm
->
tm_hour
>
13
?
PM_STR
:
AM_STR
));
return
1
;
}
else
if
(
flag
==
FROM_CHAR
)
{
if
(
strncmp
(
inout
,
PM_STR
,
2
)
==
0
)
tmfc
->
pm
=
TRUE
;
else
if
(
strncmp
(
inout
,
AM_STR
,
2
)
==
0
)
tmfc
->
am
=
TRUE
;
else
AMPM_ERROR
;
if
(
strncmp
(
inout
,
PM_STR
,
2
)
==
0
&&
tm
->
tm_hour
<
13
)
tm
->
tm_hour
+=
12
;
return
1
;
}
break
;
case
DCH_a_m
:
case
DCH_p_m
:
if
(
flag
==
TO_CHAR
)
{
strcpy
(
inout
,
((
tm
->
tm_hour
>
11
&&
tm
->
tm_hour
<
24
)
?
p_m_STR
:
a_m_STR
));
strcpy
(
inout
,
(
tm
->
tm_hour
>
13
?
p_m_STR
:
a_m_STR
));
return
3
;
}
else
if
(
flag
==
FROM_CHAR
)
{
if
(
strncmp
(
inout
,
p_m_STR
,
4
)
==
0
)
tmfc
->
pm
=
TRUE
;
else
if
(
strncmp
(
inout
,
a_m_STR
,
4
)
==
0
)
tmfc
->
am
=
TRUE
;
else
AMPM_ERROR
;
if
(
strncmp
(
inout
,
p_m_STR
,
4
)
==
0
&&
tm
->
tm_hour
<
13
)
tm
->
tm_hour
+=
12
;
return
3
;
}
break
;
case
DCH_am
:
case
DCH_pm
:
if
(
flag
==
TO_CHAR
)
{
strcpy
(
inout
,
((
tm
->
tm_hour
>
11
&&
tm
->
tm_hour
<
24
)
?
pm_STR
:
am_STR
));
strcpy
(
inout
,
(
tm
->
tm_hour
>
13
?
pm_STR
:
am_STR
));
return
1
;
}
else
if
(
flag
==
FROM_CHAR
)
{
if
(
strncmp
(
inout
,
pm_STR
,
2
)
==
0
)
tmfc
->
pm
=
TRUE
;
else
if
(
strncmp
(
inout
,
am_STR
,
2
)
==
0
)
tmfc
->
am
=
TRUE
;
else
AMPM_ERROR
;
if
(
strncmp
(
inout
,
pm_STR
,
2
)
==
0
&&
tm
->
tm_hour
<
13
)
tm
->
tm_hour
+=
12
;
return
1
;
}
break
;
case
DCH_HH
:
case
DCH_HH12
:
if
(
flag
==
TO_CHAR
)
...
...
@@ -1640,21 +1606,22 @@ dch_time(int arg, char *inout, int suf, int flag, FormatNode *node)
return
strlen
(
p_inout
)
-
1
;
else
return
1
;
}
else
if
(
flag
==
FROM_CHAR
)
{
if
(
S_FM
(
suf
))
{
sscanf
(
inout
,
"%d"
,
&
tm
fc
->
hh
);
return
int4len
((
int4
)
tm
fc
->
hh
)
-
1
+
SKIP_THth
(
suf
);
sscanf
(
inout
,
"%d"
,
&
tm
->
tm_hour
);
return
int4len
((
int4
)
tm
->
tm_hour
)
-
1
+
SKIP_THth
(
suf
);
}
else
{
sscanf
(
inout
,
"%02d"
,
&
tm
fc
->
hh
);
sscanf
(
inout
,
"%02d"
,
&
tm
->
tm_hour
);
return
1
+
SKIP_THth
(
suf
);
}
}
break
;
case
DCH_HH24
:
if
(
flag
==
TO_CHAR
)
{
...
...
@@ -1671,16 +1638,16 @@ dch_time(int arg, char *inout, int suf, int flag, FormatNode *node)
{
if
(
S_FM
(
suf
))
{
sscanf
(
inout
,
"%d"
,
&
tm
fc
->
hh
);
return
int4len
((
int4
)
tm
fc
->
hh
)
-
1
+
SKIP_THth
(
suf
);
sscanf
(
inout
,
"%d"
,
&
tm
->
tm_hour
);
return
int4len
((
int4
)
tm
->
tm_hour
)
-
1
+
SKIP_THth
(
suf
);
}
else
{
sscanf
(
inout
,
"%02d"
,
&
tm
fc
->
hh
);
sscanf
(
inout
,
"%02d"
,
&
tm
->
tm_hour
);
return
1
+
SKIP_THth
(
suf
);
}
}
break
;
case
DCH_MI
:
if
(
flag
==
TO_CHAR
)
{
...
...
@@ -1697,16 +1664,15 @@ dch_time(int arg, char *inout, int suf, int flag, FormatNode *node)
{
if
(
S_FM
(
suf
))
{
sscanf
(
inout
,
"%d"
,
&
tm
fc
->
mi
);
return
int4len
((
int4
)
tm
fc
->
mi
)
-
1
+
SKIP_THth
(
suf
);
sscanf
(
inout
,
"%d"
,
&
tm
->
tm_min
);
return
int4len
((
int4
)
tm
->
tm_min
)
-
1
+
SKIP_THth
(
suf
);
}
else
{
sscanf
(
inout
,
"%02d"
,
&
tm
fc
->
mi
);
sscanf
(
inout
,
"%02d"
,
&
tm
->
tm_min
);
return
1
+
SKIP_THth
(
suf
);
}
}
break
;
case
DCH_SS
:
if
(
flag
==
TO_CHAR
)
{
...
...
@@ -1717,21 +1683,21 @@ dch_time(int arg, char *inout, int suf, int flag, FormatNode *node)
return
strlen
(
p_inout
)
-
1
;
else
return
1
;
}
else
if
(
flag
==
FROM_CHAR
)
{
if
(
S_FM
(
suf
))
{
sscanf
(
inout
,
"%d"
,
&
tm
fc
->
ss
);
return
int4len
((
int4
)
tm
fc
->
ss
)
-
1
+
SKIP_THth
(
suf
);
sscanf
(
inout
,
"%d"
,
&
tm
->
tm_sec
);
return
int4len
((
int4
)
tm
->
tm_sec
)
-
1
+
SKIP_THth
(
suf
);
}
else
{
sscanf
(
inout
,
"%02d"
,
&
tm
fc
->
ss
);
sscanf
(
inout
,
"%02d"
,
&
tm
->
tm_sec
);
return
1
+
SKIP_THth
(
suf
);
}
}
break
;
case
DCH_SSSS
:
if
(
flag
==
TO_CHAR
)
{
...
...
@@ -1743,11 +1709,7 @@ dch_time(int arg, char *inout, int suf, int flag, FormatNode *node)
return
strlen
(
p_inout
)
-
1
;
}
else
if
(
flag
==
FROM_CHAR
)
{
sscanf
(
inout
,
"%d"
,
&
tmfc
->
ssss
);
return
int4len
((
int4
)
tmfc
->
ssss
)
-
1
+
SKIP_THth
(
suf
);
}
break
;
elog
(
ERROR
,
"to_timestamp(): SSSS is not supported"
);
}
return
-
1
;
}
...
...
@@ -1784,94 +1746,117 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
{
if
(
arg
==
DCH_MONTH
||
arg
==
DCH_Month
||
arg
==
DCH_month
)
{
tmfc
->
mm
=
seq_search
(
inout
,
months_full
,
ONE_UPPER
,
FULL_SIZ
,
&
len
)
+
1
;
tm
->
tm_mon
=
seq_search
(
inout
,
months_full
,
ONE_UPPER
,
FULL_SIZ
,
&
len
);
CHECK_SEQ_SEARCH
(
len
,
"MONTH/Month/month"
);
++
tm
->
tm_mon
;
if
(
S_FM
(
suf
))
return
len
-
1
;
else
return
8
;
}
else
if
(
arg
==
DCH_MON
||
arg
==
DCH_Mon
||
arg
==
DCH_mon
)
{
tmfc
->
mm
=
seq_search
(
inout
,
months
,
ONE_UPPER
,
MAX_MON_LEN
,
&
len
)
+
1
;
tm
->
tm_mon
=
seq_search
(
inout
,
months
,
ONE_UPPER
,
MAX_MON_LEN
,
&
len
);
CHECK_SEQ_SEARCH
(
len
,
"MON/Mon/mon"
);
++
tm
->
tm_mon
;
return
2
;
}
else
if
(
arg
==
DCH_DAY
||
arg
==
DCH_Day
||
arg
==
DCH_day
)
{
tmfc
->
d
=
seq_search
(
inout
,
days
,
ONE_UPPER
,
FULL_SIZ
,
&
len
);
tm
->
tm_wday
=
seq_search
(
inout
,
days
,
ONE_UPPER
,
FULL_SIZ
,
&
len
);
CHECK_SEQ_SEARCH
(
len
,
"DAY/Day/day"
);
if
(
S_FM
(
suf
))
return
len
-
1
;
else
return
8
;
}
else
if
(
arg
==
DCH_DY
||
arg
==
DCH_Dy
||
arg
==
DCH_dy
)
{
tmfc
->
d
=
seq_search
(
inout
,
days
,
ONE_UPPER
,
MAX_DY_LEN
,
&
len
);
tm
->
tm_wday
=
seq_search
(
inout
,
days
,
ONE_UPPER
,
MAX_DY_LEN
,
&
len
);
CHECK_SEQ_SEARCH
(
len
,
"DY/Dy/dy"
);
return
2
;
}
}
switch
(
arg
)
{
case
DCH_A_D
:
case
DCH_B_C
:
if
(
flag
==
TO_CHAR
)
{
strcpy
(
inout
,
(
tm
->
tm_year
<
0
?
B_C_STR
:
A_D_STR
));
return
3
;
}
else
if
(
flag
==
FROM_CHAR
)
{
if
(
strncmp
(
inout
,
B_C_STR
,
4
)
==
0
)
tmfc
->
bc
=
TRUE
;
if
(
strncmp
(
inout
,
B_C_STR
,
4
)
==
0
&&
tm
->
tm_year
>
0
)
tm
->
tm_year
=
-
(
tm
->
tm_year
);
if
(
tm
->
tm_year
<
0
)
tm
->
tm_year
=
tm
->
tm_year
+
1
;
return
3
;
}
break
;
case
DCH_AD
:
case
DCH_BC
:
if
(
flag
==
TO_CHAR
)
{
strcpy
(
inout
,
(
tm
->
tm_year
<
0
?
BC_STR
:
AD_STR
));
return
1
;
}
else
if
(
flag
==
FROM_CHAR
)
{
if
(
strncmp
(
inout
,
BC_STR
,
2
)
==
0
)
tmfc
->
bc
=
TRUE
;
if
(
strncmp
(
inout
,
BC_STR
,
2
)
==
0
&&
tm
->
tm_year
>
0
)
tm
->
tm_year
=
-
(
tm
->
tm_year
);
if
(
tm
->
tm_year
<
0
)
tm
->
tm_year
=
tm
->
tm_year
+
1
;
return
1
;
}
break
;
case
DCH_a_d
:
case
DCH_b_c
:
if
(
flag
==
TO_CHAR
)
{
strcpy
(
inout
,
(
tm
->
tm_year
<
0
?
b_c_STR
:
a_d_STR
));
return
3
;
}
else
if
(
flag
==
FROM_CHAR
)
{
if
(
strncmp
(
inout
,
b_c_STR
,
4
)
==
0
)
tmfc
->
bc
=
TRUE
;
if
(
strncmp
(
inout
,
b_c_STR
,
4
)
==
0
&&
tm
->
tm_year
>
0
)
tm
->
tm_year
=
-
(
tm
->
tm_year
);
if
(
tm
->
tm_year
<
0
)
tm
->
tm_year
=
tm
->
tm_year
+
1
;
return
3
;
}
break
;
case
DCH_ad
:
case
DCH_bc
:
if
(
flag
==
TO_CHAR
)
{
strcpy
(
inout
,
(
tm
->
tm_year
<
0
?
bc_STR
:
ad_STR
));
return
1
;
}
else
if
(
flag
==
FROM_CHAR
)
{
if
(
strncmp
(
inout
,
bc_STR
,
2
)
==
0
)
tmfc
->
bc
=
TRUE
;
if
(
strncmp
(
inout
,
bc_STR
,
2
)
==
0
&&
tm
->
tm_year
>
0
)
tm
->
tm_year
=
-
(
tm
->
tm_year
);
if
(
tm
->
tm_year
<
0
)
tm
->
tm_year
=
tm
->
tm_year
+
1
;
return
1
;
}
break
;
case
DCH_MONTH
:
strcpy
(
inout
,
months_full
[
tm
->
tm_mon
-
1
]);
sprintf
(
inout
,
"%*s"
,
S_FM
(
suf
)
?
0
:
-
9
,
str_toupper
(
inout
));
...
...
@@ -1919,21 +1904,22 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
return
strlen
(
p_inout
)
-
1
;
else
return
1
;
}
else
if
(
flag
==
FROM_CHAR
)
{
if
(
S_FM
(
suf
))
{
sscanf
(
inout
,
"%d"
,
&
tm
fc
->
mm
);
return
int4len
((
int4
)
tm
fc
->
mm
)
-
1
+
SKIP_THth
(
suf
);
sscanf
(
inout
,
"%d"
,
&
tm
->
tm_mon
);
return
int4len
((
int4
)
tm
->
tm_mon
)
-
1
+
SKIP_THth
(
suf
);
}
else
{
sscanf
(
inout
,
"%02d"
,
&
tm
fc
->
mm
);
sscanf
(
inout
,
"%02d"
,
&
tm
->
tm_mon
);
return
1
+
SKIP_THth
(
suf
);
}
}
break
;
case
DCH_DAY
:
strcpy
(
inout
,
days
[
tm
->
tm_wday
]);
sprintf
(
inout
,
"%*s"
,
S_FM
(
suf
)
?
0
:
-
9
,
str_toupper
(
inout
));
...
...
@@ -1981,21 +1967,22 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
return
strlen
(
p_inout
)
-
1
;
else
return
2
;
}
else
if
(
flag
==
FROM_CHAR
)
{
if
(
S_FM
(
suf
))
{
sscanf
(
inout
,
"%d"
,
&
tm
fc
->
ddd
);
return
int4len
((
int4
)
tm
fc
->
ddd
)
-
1
+
SKIP_THth
(
suf
);
sscanf
(
inout
,
"%d"
,
&
tm
->
tm_yday
);
return
int4len
((
int4
)
tm
->
tm_yday
)
-
1
+
SKIP_THth
(
suf
);
}
else
{
sscanf
(
inout
,
"%03d"
,
&
tm
fc
->
ddd
);
sscanf
(
inout
,
"%03d"
,
&
tm
->
tm_yday
);
return
2
+
SKIP_THth
(
suf
);
}
}
break
;
case
DCH_DD
:
if
(
flag
==
TO_CHAR
)
{
...
...
@@ -2006,21 +1993,21 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
return
strlen
(
p_inout
)
-
1
;
else
return
1
;
}
else
if
(
flag
==
FROM_CHAR
)
{
if
(
S_FM
(
suf
))
{
sscanf
(
inout
,
"%d"
,
&
tm
fc
->
dd
);
return
int4len
((
int4
)
tm
fc
->
dd
)
-
1
+
SKIP_THth
(
suf
);
sscanf
(
inout
,
"%d"
,
&
tm
->
tm_mday
);
return
int4len
((
int4
)
tm
->
tm_mday
)
-
1
+
SKIP_THth
(
suf
);
}
else
{
sscanf
(
inout
,
"%02d"
,
&
tm
fc
->
dd
);
sscanf
(
inout
,
"%02d"
,
&
tm
->
tm_mday
);
return
1
+
SKIP_THth
(
suf
);
}
}
break
;
case
DCH_D
:
if
(
flag
==
TO_CHAR
)
{
...
...
@@ -2034,15 +2021,17 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
}
else
if
(
flag
==
FROM_CHAR
)
{
sscanf
(
inout
,
"%1d"
,
&
tmfc
->
d
);
sscanf
(
inout
,
"%1d"
,
&
tm
->
tm_wday
);
if
(
tm
->
tm_wday
)
--
tm
->
tm_wday
;
return
0
+
SKIP_THth
(
suf
);
}
break
;
case
DCH_WW
:
if
(
flag
==
TO_CHAR
)
{
sprintf
(
inout
,
"%0*d"
,
S_FM
(
suf
)
?
0
:
2
,
(
tm
->
tm_yday
-
1
)
/
7
+
1
);
(
tm
->
tm_yday
-
tm
->
tm_wday
+
7
)
/
7
);
if
(
S_THth
(
suf
))
str_numth
(
p_inout
,
inout
,
S_TH_TYPE
(
suf
));
if
(
S_FM
(
suf
)
||
S_THth
(
suf
))
...
...
@@ -2052,19 +2041,7 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
}
else
if
(
flag
==
FROM_CHAR
)
{
if
(
S_FM
(
suf
))
{
sscanf
(
inout
,
"%d"
,
&
tmfc
->
ww
);
return
int4len
((
int4
)
tmfc
->
ww
)
-
1
+
SKIP_THth
(
suf
);
}
else
{
sscanf
(
inout
,
"%02d"
,
&
tmfc
->
ww
);
return
1
+
SKIP_THth
(
suf
);
}
}
break
;
elog
(
ERROR
,
"to_datatime(): WW is not supported"
);
case
DCH_Q
:
if
(
flag
==
TO_CHAR
)
{
...
...
@@ -2078,11 +2055,8 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
}
else
if
(
flag
==
FROM_CHAR
)
{
sscanf
(
inout
,
"%1d"
,
&
tmfc
->
q
);
return
0
+
SKIP_THth
(
suf
);
}
break
;
elog
(
ERROR
,
"to_datatime(): Q is not supported"
);
case
DCH_CC
:
if
(
flag
==
TO_CHAR
)
{
...
...
@@ -2097,11 +2071,7 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
}
else
if
(
flag
==
FROM_CHAR
)
{
sscanf
(
inout
,
"%d"
,
&
tmfc
->
cc
);
return
int4len
((
int4
)
tmfc
->
cc
)
+
SKIP_THth
(
suf
)
-
1
;
}
break
;
elog
(
ERROR
,
"to_datatime(): CC is not supported"
);
case
DCH_Y_YYY
:
if
(
flag
==
TO_CHAR
)
{
...
...
@@ -2109,23 +2079,35 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
sprintf
(
inout
,
"%d,%03d"
,
i
,
YEAR_ABS
(
tm
->
tm_year
)
-
(
i
*
1000
));
if
(
S_THth
(
suf
))
str_numth
(
p_inout
,
inout
,
S_TH_TYPE
(
suf
));
/*
* if (tm->tm_year < 0) strcat(inout, BC_STR_ORIG);
*/
return
strlen
(
p_inout
)
-
1
;
}
else
if
(
flag
==
FROM_CHAR
)
{
int
cc
;
int
cc
,
yy
;
sscanf
(
inout
,
"%d,%03d"
,
&
cc
,
&
tmfc
->
yy
yy
);
tm
fc
->
yyyy
+=
(
cc
*
1000
)
;
sscanf
(
inout
,
"%d,%03d"
,
&
cc
,
&
yy
);
tm
->
tm_year
=
(
cc
*
1000
)
+
yy
;
if
(
!
S_FM
(
suf
)
&&
tm
fc
->
yyyy
<=
9999
&&
tmfc
->
yyyy
>=
-
9999
)
if
(
!
S_FM
(
suf
)
&&
tm
->
tm_year
<=
9999
&&
tm
->
tm_year
>=
-
9999
)
len
=
5
;
else
len
=
int4len
((
int4
)
tm
fc
->
yyyy
)
+
1
;
len
=
int4len
((
int4
)
tm
->
tm_year
)
+
1
;
len
+=
SKIP_THth
(
suf
);
/*
* AC/BC if (is_acdc(inout+len, &len) < 0 && tm->tm_year >
* 0) tm->tm_year = -(tm->tm_year); if (tm->tm_year < 0)
* tm->tm_year = tm->tm_year+1;
*/
return
len
-
1
;
}
break
;
case
DCH_YYYY
:
if
(
flag
==
TO_CHAR
)
{
...
...
@@ -2135,19 +2117,30 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
sprintf
(
inout
,
"%d"
,
YEAR_ABS
(
tm
->
tm_year
));
if
(
S_THth
(
suf
))
str_numth
(
p_inout
,
inout
,
S_TH_TYPE
(
suf
));
/*
* if (tm->tm_year < 0) strcat(inout, BC_STR_ORIG);
*/
return
strlen
(
p_inout
)
-
1
;
}
else
if
(
flag
==
FROM_CHAR
)
{
sscanf
(
inout
,
"%d"
,
&
tm
fc
->
yyyy
);
if
(
!
S_FM
(
suf
)
&&
tm
fc
->
yyyy
<=
9999
&&
tmfc
->
yyyy
>=
-
9999
)
sscanf
(
inout
,
"%d"
,
&
tm
->
tm_year
);
if
(
!
S_FM
(
suf
)
&&
tm
->
tm_year
<=
9999
&&
tm
->
tm_year
>=
-
9999
)
len
=
4
;
else
len
=
int4len
((
int4
)
tm
fc
->
yyyy
);
len
=
int4len
((
int4
)
tm
->
tm_year
);
len
+=
SKIP_THth
(
suf
);
/*
* AC/BC if (is_acdc(inout+len, &len) < 0 && tm->tm_year >
* 0) tm->tm_year = -(tm->tm_year); if (tm->tm_year < 0)
* tm->tm_year = tm->tm_year+1;
*/
return
len
-
1
;
}
break
;
case
DCH_YYY
:
if
(
flag
==
TO_CHAR
)
{
...
...
@@ -2160,13 +2153,17 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
return
4
;
}
return
2
;
}
else
if
(
flag
==
FROM_CHAR
)
{
sscanf
(
inout
,
"%03d"
,
&
tmfc
->
yyyy
);
int
yy
;
sscanf
(
inout
,
"%03d"
,
&
yy
);
tm
->
tm_year
=
(
tm
->
tm_year
/
1000
)
*
1000
+
yy
;
return
2
+
SKIP_THth
(
suf
);
}
break
;
case
DCH_YY
:
if
(
flag
==
TO_CHAR
)
{
...
...
@@ -2179,13 +2176,17 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
return
3
;
}
return
1
;
}
else
if
(
flag
==
FROM_CHAR
)
{
sscanf
(
inout
,
"%02d"
,
&
tmfc
->
yyyy
);
int
yy
;
sscanf
(
inout
,
"%02d"
,
&
yy
);
tm
->
tm_year
=
(
tm
->
tm_year
/
100
)
*
100
+
yy
;
return
1
+
SKIP_THth
(
suf
);
}
break
;
case
DCH_Y
:
if
(
flag
==
TO_CHAR
)
{
...
...
@@ -2202,10 +2203,13 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
}
else
if
(
flag
==
FROM_CHAR
)
{
sscanf
(
inout
,
"%1d"
,
&
tmfc
->
yyyy
);
int
yy
;
sscanf
(
inout
,
"%1d"
,
&
yy
);
tm
->
tm_year
=
(
tm
->
tm_year
/
10
)
*
10
+
yy
;
return
0
+
SKIP_THth
(
suf
);
}
break
;
case
DCH_RM
:
if
(
flag
==
TO_CHAR
)
{
...
...
@@ -2215,17 +2219,19 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
return
strlen
(
p_inout
)
-
1
;
else
return
3
;
}
else
if
(
flag
==
FROM_CHAR
)
{
tm
fc
->
mm
=
12
-
seq_search
(
inout
,
rm_months_upper
,
ALL_UPPER
,
FULL_SIZ
,
&
len
);
tm
->
tm_mon
=
11
-
seq_search
(
inout
,
rm_months_upper
,
ALL_UPPER
,
FULL_SIZ
,
&
len
);
CHECK_SEQ_SEARCH
(
len
,
"RM"
);
++
tm
->
tm_mon
;
if
(
S_FM
(
suf
))
return
len
-
1
;
else
return
3
;
}
break
;
case
DCH_rm
:
if
(
flag
==
TO_CHAR
)
{
...
...
@@ -2239,31 +2245,30 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
}
else
if
(
flag
==
FROM_CHAR
)
{
tm
fc
->
mm
=
12
-
seq_search
(
inout
,
rm_months_lower
,
ALL_UPPER
,
FULL_SIZ
,
&
len
);
tm
->
tm_mon
=
11
-
seq_search
(
inout
,
rm_months_lower
,
ALL_UPPER
,
FULL_SIZ
,
&
len
);
CHECK_SEQ_SEARCH
(
len
,
"rm"
);
++
tm
->
tm_mon
;
if
(
S_FM
(
suf
))
return
len
-
1
;
else
return
3
;
}
break
;
case
DCH_W
:
if
(
flag
==
TO_CHAR
)
{
sprintf
(
inout
,
"%d"
,
(
tm
->
tm_mday
-
1
)
/
7
+
1
);
sprintf
(
inout
,
"%d"
,
(
tm
->
tm_mday
-
tm
->
tm_wday
+
7
)
/
7
);
if
(
S_THth
(
suf
))
{
str_numth
(
p_inout
,
inout
,
S_TH_TYPE
(
suf
));
return
2
;
}
return
0
;
}
else
if
(
flag
==
FROM_CHAR
)
{
sscanf
(
inout
,
"%1d"
,
&
tmfc
->
w
);
return
0
+
SKIP_THth
(
suf
);
}
break
;
elog
(
ERROR
,
"to_datatime(): W is not supported"
);
case
DCH_J
:
if
(
flag
==
TO_CHAR
)
{
...
...
@@ -2273,11 +2278,7 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
return
strlen
(
p_inout
)
-
1
;
}
else
if
(
flag
==
FROM_CHAR
)
{
sscanf
(
inout
,
"%d"
,
&
tmfc
->
j
);
return
int4len
((
int4
)
tmfc
->
j
)
+
SKIP_THth
(
suf
)
-
1
;
}
break
;
elog
(
ERROR
,
"to_datatime(): J is not supported"
);
}
return
-
1
;
}
...
...
@@ -2369,7 +2370,6 @@ DCH_cache_search(char *str)
}
/****************************************************************************
* Public routines
***************************************************************************/
...
...
@@ -2378,9 +2378,11 @@ DCH_cache_search(char *str)
* TIMESTAMP to_char()
* -------------------
*/
text
*
timestamp_to_char
(
Timestamp
*
dt
,
text
*
fmt
)
Datum
timestamp_to_char
(
PG_FUNCTION_ARGS
)
{
Timestamp
dt
=
PG_GETARG_TIMESTAMP
(
0
);
text
*
fmt
=
PG_GETARG_TEXT_P
(
1
);
text
*
result
,
*
result_tmp
;
FormatNode
*
format
;
...
...
@@ -2392,26 +2394,33 @@ timestamp_to_char(Timestamp *dt, text *fmt)
flag
=
0
,
x
=
0
;
if
((
!
PointerIsValid
(
dt
))
||
(
!
PointerIsValid
(
fmt
)))
return
NULL
;
len
=
VARSIZE
(
fmt
)
-
VARHDRSZ
;
if
((
!
len
)
||
(
TIMESTAMP_NOT_FINITE
(
*
dt
)))
return
textin
(
""
);
if
((
!
len
)
||
(
TIMESTAMP_NOT_FINITE
(
dt
)))
return
PointerGetDatum
(
textin
(
""
)
);
ZERO_tm
(
tm
);
tm
->
tm_sec
=
0
;
tm
->
tm_year
=
0
;
tm
->
tm_min
=
0
;
tm
->
tm_wday
=
0
;
tm
->
tm_hour
=
0
;
tm
->
tm_yday
=
0
;
tm
->
tm_mday
=
1
;
tm
->
tm_isdst
=
0
;
tm
->
tm_mon
=
1
;
if
(
TIMESTAMP_IS_EPOCH
(
*
dt
))
if
(
TIMESTAMP_IS_EPOCH
(
dt
))
{
x
=
timestamp2tm
(
SetTimestamp
(
*
dt
),
NULL
,
tm
,
&
fsec
,
NULL
);
x
=
timestamp2tm
(
SetTimestamp
(
dt
),
NULL
,
tm
,
&
fsec
,
NULL
);
}
else
if
(
TIMESTAMP_IS_CURRENT
(
*
dt
))
else
if
(
TIMESTAMP_IS_CURRENT
(
dt
))
{
x
=
timestamp2tm
(
SetTimestamp
(
*
dt
),
&
tz
,
tm
,
&
fsec
,
&
tzn
);
x
=
timestamp2tm
(
SetTimestamp
(
dt
),
&
tz
,
tm
,
&
fsec
,
&
tzn
);
}
else
x
=
timestamp2tm
(
*
dt
,
&
tz
,
tm
,
&
fsec
,
&
tzn
);
x
=
timestamp2tm
(
dt
,
&
tz
,
tm
,
&
fsec
,
&
tzn
);
if
(
x
!=
0
)
elog
(
ERROR
,
"to_char(): Unable to convert timestamp to tm"
);
...
...
@@ -2440,6 +2449,7 @@ timestamp_to_char(Timestamp *dt, text *fmt)
*/
if
(
len
>
DCH_CACHE_SIZE
)
{
format
=
(
FormatNode
*
)
palloc
((
len
+
1
)
*
sizeof
(
FormatNode
));
flag
=
1
;
...
...
@@ -2447,9 +2457,11 @@ timestamp_to_char(Timestamp *dt, text *fmt)
DCH_suff
,
DCH_index
,
DCH_TYPE
,
NULL
);
(
format
+
len
)
->
type
=
NODE_TYPE_END
;
/* Paranoa? */
}
else
{
/* ----------
* Use cache buffers
* ----------
...
...
@@ -2501,7 +2513,7 @@ timestamp_to_char(Timestamp *dt, text *fmt)
VARSIZE
(
result
)
=
len
+
VARHDRSZ
;
pfree
(
result_tmp
);
return
result
;
PG_RETURN_TEXT_P
(
result
)
;
}
...
...
@@ -2512,28 +2524,34 @@ timestamp_to_char(Timestamp *dt, text *fmt)
* ( to_timestamp is reverse to_char() )
* ---------------------
*/
Timestamp
*
to_timestamp
(
text
*
date_str
,
text
*
fmt
)
Datum
to_timestamp
(
PG_FUNCTION_ARGS
)
{
text
*
date_str
=
PG_GETARG_TEXT_P
(
0
);
text
*
fmt
=
PG_GETARG_TEXT_P
(
1
);
FormatNode
*
format
;
int
flag
=
0
;
Timestamp
*
result
;
Timestamp
result
;
char
*
str
;
int
len
=
0
,
fsec
=
0
,
tz
=
0
,
x
=
0
;
tz
=
0
;
if
((
!
PointerIsValid
(
date_str
))
||
(
!
PointerIsValid
(
fmt
)))
return
NULL
;
tm
->
tm_sec
=
0
;
tm
->
tm_year
=
0
;
tm
->
tm_min
=
0
;
tm
->
tm_wday
=
0
;
tm
->
tm_hour
=
0
;
tm
->
tm_yday
=
0
;
tm
->
tm_mday
=
1
;
tm
->
tm_isdst
=
0
;
tm
->
tm_mon
=
1
;
result
=
palloc
(
sizeof
(
Timestamp
));
len
=
VARSIZE
(
fmt
)
-
VARHDRSZ
;
ZERO_tmfc
(
tmfc
);
if
(
len
)
{
/* ----------
* Convert VARDATA() to string
* ----------
...
...
@@ -2549,6 +2567,7 @@ to_timestamp(text *date_str, text *fmt)
*/
if
(
len
>
DCH_CACHE_SIZE
)
{
format
=
(
FormatNode
*
)
palloc
((
len
+
1
)
*
sizeof
(
FormatNode
));
flag
=
1
;
...
...
@@ -2559,6 +2578,7 @@ to_timestamp(text *date_str, text *fmt)
}
else
{
/* ----------
* Use cache buffers
* ----------
...
...
@@ -2569,6 +2589,7 @@ to_timestamp(text *date_str, text *fmt)
if
((
ent
=
DCH_cache_search
(
str
))
==
NULL
)
{
ent
=
DCH_cache_getnew
(
str
);
/* ----------
...
...
@@ -2604,101 +2625,6 @@ to_timestamp(text *date_str, text *fmt)
pfree
(
format
);
}
/* --------------------------------------------------------------
* Convert values that user define for FROM_CHAR (to_date/to_timestamp)
* to standard 'tm'
* ----------
*/
ZERO_tm
(
tm
);
#ifdef DEBUG_TO_FROM_CHAR
NOTICE_TMFC
;
#endif
if
(
tmfc
->
ssss
)
{
if
(
tmfc
->
ssss
>
3600
)
tm
->
tm_sec
=
x
-
((
tm
->
tm_min
=
(
x
=
tmfc
->
ssss
-
((
tm
->
tm_hour
=
tmfc
->
ssss
/
3600
)
*
3600
))
/
60
)
*
60
);
else
if
(
tmfc
->
ssss
>
60
)
tm
->
tm_sec
=
tmfc
->
ssss
-
((
tm
->
tm_min
=
tmfc
->
ssss
/
60
)
*
60
);
else
tm
->
tm_sec
=
tmfc
->
ssss
;
}
if
(
tmfc
->
cc
)
tm
->
tm_year
=
(
tmfc
->
cc
-
1
)
*
100
;
if
(
tmfc
->
ww
)
tmfc
->
ddd
=
(
tmfc
->
ww
-
1
)
*
7
+
1
;
if
(
tmfc
->
w
)
tmfc
->
dd
=
(
tmfc
->
w
-
1
)
*
7
+
1
;
if
(
tmfc
->
ss
)
tm
->
tm_sec
=
tmfc
->
ss
;
if
(
tmfc
->
mi
)
tm
->
tm_min
=
tmfc
->
mi
;
if
(
tmfc
->
hh
)
tm
->
tm_hour
=
tmfc
->
hh
;
if
(
tmfc
->
pm
||
tmfc
->
am
)
{
if
(
tm
->
tm_hour
<
1
||
tm
->
tm_hour
>
12
)
elog
(
ERROR
,
"to_timestamp(): AM/PM hour must be between 1 and 12"
);
if
(
tmfc
->
pm
&&
tm
->
tm_hour
<
12
)
tm
->
tm_hour
+=
12
;
else
if
(
tmfc
->
am
&&
tm
->
tm_hour
==
12
)
tm
->
tm_hour
=
0
;
}
switch
(
tmfc
->
q
)
{
case
1
:
tm
->
tm_mday
=
1
;
tm
->
tm_mon
=
1
;
break
;
case
2
:
tm
->
tm_mday
=
1
;
tm
->
tm_mon
=
4
;
break
;
case
3
:
tm
->
tm_mday
=
1
;
tm
->
tm_mon
=
7
;
break
;
case
4
:
tm
->
tm_mday
=
1
;
tm
->
tm_mon
=
10
;
break
;
}
if
(
tmfc
->
j
)
j2date
(
tmfc
->
j
,
&
tm
->
tm_year
,
&
tm
->
tm_mon
,
&
tm
->
tm_mday
);
if
(
tmfc
->
yyyy
)
tm
->
tm_year
=
tmfc
->
yyyy
;
if
(
tmfc
->
bc
&&
tm
->
tm_year
>
0
)
tm
->
tm_year
=
-
(
tm
->
tm_year
);
if
(
tm
->
tm_year
<
0
)
tm
->
tm_year
=
tm
->
tm_year
+
1
;
if
(
tmfc
->
d
)
tm
->
tm_wday
=
tmfc
->
d
;
if
(
tmfc
->
dd
)
tm
->
tm_mday
=
tmfc
->
dd
;
if
(
tmfc
->
ddd
)
tm
->
tm_yday
=
tmfc
->
ddd
;
if
(
tmfc
->
mm
)
tm
->
tm_mon
=
tmfc
->
mm
;
if
(
tmfc
->
ddd
&&
(
tm
->
tm_mon
<=
1
||
tm
->
tm_mday
<=
1
))
{
/* count mday and mon from yday */
int
*
y
,
i
;
int
ysum
[
2
][
13
]
=
{
{
31
,
59
,
90
,
120
,
151
,
181
,
212
,
243
,
273
,
304
,
334
,
365
,
0
},
{
31
,
60
,
91
,
121
,
152
,
182
,
213
,
244
,
274
,
305
,
335
,
366
,
0
}};
if
(
!
tm
->
tm_year
)
elog
(
ERROR
,
"to_timestamp() cat't convert yday without year information"
);
y
=
ysum
[
isleap
(
tm
->
tm_year
)
];
for
(
i
=
0
;
i
<=
11
;
i
++
)
{
if
(
tm
->
tm_yday
<
y
[
i
])
break
;
}
if
(
tm
->
tm_mon
<=
1
)
tm
->
tm_mon
=
i
+
1
;
if
(
tm
->
tm_mday
<=
1
)
tm
->
tm_mday
=
i
==
0
?
tm
->
tm_yday
:
tm
->
tm_yday
-
y
[
i
-
1
];
}
/* -------------------------------------------------------------- */
#ifdef DEBUG_TO_FROM_CHAR
NOTICE_TM
;
#endif
...
...
@@ -2744,10 +2670,10 @@ to_timestamp(text *date_str, text *fmt)
#ifdef DEBUG_TO_FROM_CHAR
NOTICE_TM
;
#endif
if
(
tm2timestamp
(
tm
,
fsec
,
&
tz
,
result
)
!=
0
)
elog
(
ERROR
,
"to_
datatime
(): can't convert 'tm' to timestamp."
);
if
(
tm2timestamp
(
tm
,
fsec
,
&
tz
,
&
result
)
!=
0
)
elog
(
ERROR
,
"to_
timestamp
(): can't convert 'tm' to timestamp."
);
return
result
;
PG_RETURN_TIMESTAMP
(
result
)
;
}
/* ----------
...
...
@@ -2755,10 +2681,13 @@ to_timestamp(text *date_str, text *fmt)
* Make Date from date_str which is formated at argument 'fmt'
* ----------
*/
Dat
eADT
to_date
(
text
*
date_str
,
text
*
fmt
)
Dat
um
to_date
(
PG_FUNCTION_ARGS
)
{
return
timestamp_date
(
to_timestamp
(
date_str
,
fmt
));
/* Quick hack: since our inputs are just like to_timestamp,
* hand over the whole input info struct...
*/
return
DirectFunctionCall1
(
timestamp_date
,
to_timestamp
(
fcinfo
));
}
/**********************************************************************
...
...
@@ -3922,13 +3851,11 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number,
* ----------
*/
#define NUM_TOCHAR_prepare { \
if (!PointerIsValid(fmt)) \
return NULL; \
\
len = VARSIZE(fmt) - VARHDRSZ; \
\
if (
!len
) \
return
textin(""
); \
if (
len <= 0
) \
return
PointerGetDatum(textin("")
); \
\
result = (text *) palloc( (len * NUM_MAX_ITEM_SIZ) + 1 + VARHDRSZ); \
format = NUM_cache(len, &Num, VARDATA(fmt), &flag); \
...
...
@@ -3965,26 +3892,24 @@ NUM_processor(FormatNode *node, NUMDesc *Num, char *inout, char *number,
* NUMERIC to_number() (convert string to numeric)
* -------------------
*/
Numeric
numeric_to_number
(
text
*
value
,
text
*
fmt
)
Datum
numeric_to_number
(
PG_FUNCTION_ARGS
)
{
text
*
value
=
PG_GETARG_TEXT_P
(
0
);
text
*
fmt
=
PG_GETARG_TEXT_P
(
1
);
NUMDesc
Num
;
Numeric
result
;
Datum
result
;
FormatNode
*
format
;
char
*
numstr
;
int
flag
=
0
;
int
len
=
0
;
int
scale
,
precision
;
if
((
!
PointerIsValid
(
value
))
||
(
!
PointerIsValid
(
fmt
)))
return
NULL
;
len
=
VARSIZE
(
fmt
)
-
VARHDRSZ
;
if
(
!
len
)
return
numeric_in
(
NULL
,
0
,
0
);
if
(
len
<=
0
)
PG_RETURN_NULL
(
);
format
=
NUM_cache
(
len
,
&
Num
,
VARDATA
(
fmt
),
&
flag
);
...
...
@@ -3999,7 +3924,10 @@ numeric_to_number(text *value, text *fmt)
if
(
flag
)
pfree
(
format
);
result
=
numeric_in
(
numstr
,
0
,
((
precision
<<
16
)
|
scale
)
+
VARHDRSZ
);
result
=
DirectFunctionCall3
(
numeric_in
,
CStringGetDatum
(
numstr
),
ObjectIdGetDatum
(
InvalidOid
),
Int32GetDatum
(((
precision
<<
16
)
|
scale
)
+
VARHDRSZ
));
pfree
(
numstr
);
return
result
;
}
...
...
@@ -4008,9 +3936,11 @@ numeric_to_number(text *value, text *fmt)
* NUMERIC to_char()
* ------------------
*/
text
*
numeric_to_char
(
Numeric
value
,
text
*
fmt
)
Datum
numeric_to_char
(
PG_FUNCTION_ARGS
)
{
Numeric
value
=
PG_GETARG_NUMERIC
(
0
);
text
*
fmt
=
PG_GETARG_TEXT_P
(
1
);
NUMDesc
Num
;
FormatNode
*
format
;
text
*
result
,
...
...
@@ -4022,7 +3952,7 @@ numeric_to_char(Numeric value, text *fmt)
char
*
numstr
,
*
orgnum
,
*
p
;
Numeric
x
=
NULL
;
Numeric
x
;
NUM_TOCHAR_prepare
;
...
...
@@ -4032,10 +3962,11 @@ numeric_to_char(Numeric value, text *fmt)
*/
if
(
IS_ROMAN
(
&
Num
))
{
x
=
numeric_round
(
value
,
0
);
x
=
DatumGetNumeric
(
DirectFunctionCall2
(
numeric_round
,
NumericGetDatum
(
value
),
Int32GetDatum
(
0
)));
numstr
=
orgnum
=
int_to_roman
(
numeric_int4
(
x
));
pfree
(
x
);
}
else
{
...
...
@@ -4043,8 +3974,10 @@ numeric_to_char(Numeric value, text *fmt)
if
(
IS_MULTI
(
&
Num
))
{
Numeric
a
=
int4_numeric
(
10
);
Numeric
b
=
int4_numeric
(
Num
.
multi
);
Numeric
a
=
DatumGetNumeric
(
DirectFunctionCall1
(
int4_numeric
,
Int32GetDatum
(
10
)));
Numeric
b
=
DatumGetNumeric
(
DirectFunctionCall1
(
int4_numeric
,
Int32GetDatum
(
Num
.
multi
)));
x
=
numeric_power
(
a
,
b
);
val
=
numeric_mul
(
value
,
x
);
...
...
@@ -4054,8 +3987,11 @@ numeric_to_char(Numeric value, text *fmt)
Num
.
pre
+=
Num
.
multi
;
}
x
=
numeric_round
(
val
,
Num
.
post
);
orgnum
=
numeric_out
(
x
);
x
=
DatumGetNumeric
(
DirectFunctionCall2
(
numeric_round
,
NumericGetDatum
(
val
),
Int32GetDatum
(
Num
.
post
)));
orgnum
=
DatumGetCString
(
DirectFunctionCall1
(
numeric_out
,
NumericGetDatum
(
x
)));
pfree
(
x
);
if
(
*
orgnum
==
'-'
)
...
...
@@ -4088,16 +4024,18 @@ numeric_to_char(Numeric value, text *fmt)
}
NUM_TOCHAR_finish
;
return
result
;
PG_RETURN_TEXT_P
(
result
)
;
}
/* ---------------
* INT4 to_char()
* ---------------
*/
text
*
int4_to_char
(
int32
value
,
text
*
fmt
)
Datum
int4_to_char
(
PG_FUNCTION_ARGS
)
{
int32
value
=
PG_GETARG_INT32
(
0
);
text
*
fmt
=
PG_GETARG_TEXT_P
(
1
);
NUMDesc
Num
;
FormatNode
*
format
;
text
*
result
,
...
...
@@ -4118,7 +4056,6 @@ int4_to_char(int32 value, text *fmt)
if
(
IS_ROMAN
(
&
Num
))
{
numstr
=
orgnum
=
int_to_roman
(
value
);
}
else
{
...
...
@@ -4171,16 +4108,18 @@ int4_to_char(int32 value, text *fmt)
}
NUM_TOCHAR_finish
;
return
result
;
PG_RETURN_TEXT_P
(
result
)
;
}
/* ---------------
* INT8 to_char()
* ---------------
*/
text
*
int8_to_char
(
int64
*
value
,
text
*
fmt
)
Datum
int8_to_char
(
PG_FUNCTION_ARGS
)
{
int64
value
=
PG_GETARG_INT64
(
0
);
text
*
fmt
=
PG_GETARG_TEXT_P
(
1
);
NUMDesc
Num
;
FormatNode
*
format
;
text
*
result
,
...
...
@@ -4200,8 +4139,9 @@ int8_to_char(int64 *value, text *fmt)
*/
if
(
IS_ROMAN
(
&
Num
))
{
numstr
=
orgnum
=
int_to_roman
(
int84
(
value
));
/* Currently don't support int8 conversion to roman... */
numstr
=
orgnum
=
int_to_roman
(
DatumGetInt32
(
DirectFunctionCall1
(
int84
,
Int64GetDatum
(
value
))));
}
else
{
...
...
@@ -4209,11 +4149,15 @@ int8_to_char(int64 *value, text *fmt)
{
double
multi
=
pow
((
double
)
10
,
(
double
)
Num
.
multi
);
orgnum
=
int8out
(
int8mul
(
value
,
dtoi8
((
float64
)
&
multi
)));
value
=
DatumGetInt64
(
DirectFunctionCall2
(
int8mul
,
Int64GetDatum
(
value
),
DirectFunctionCall1
(
dtoi8
,
Float8GetDatum
(
multi
))));
Num
.
pre
+=
Num
.
multi
;
}
else
orgnum
=
int8out
(
value
);
orgnum
=
DatumGetCString
(
DirectFunctionCall1
(
int8out
,
Int64GetDatum
(
value
)));
len
=
strlen
(
orgnum
);
if
(
*
orgnum
==
'-'
)
...
...
@@ -4252,16 +4196,18 @@ int8_to_char(int64 *value, text *fmt)
}
NUM_TOCHAR_finish
;
return
result
;
PG_RETURN_TEXT_P
(
result
)
;
}
/* -----------------
* FLOAT4 to_char()
* -----------------
*/
text
*
float4_to_char
(
float32
value
,
text
*
fmt
)
Datum
float4_to_char
(
PG_FUNCTION_ARGS
)
{
float4
value
=
PG_GETARG_FLOAT4
(
0
);
text
*
fmt
=
PG_GETARG_TEXT_P
(
1
);
NUMDesc
Num
;
FormatNode
*
format
;
text
*
result
,
...
...
@@ -4278,30 +4224,30 @@ float4_to_char(float32 value, text *fmt)
if
(
IS_ROMAN
(
&
Num
))
{
numstr
=
orgnum
=
int_to_roman
((
int
)
rint
(
*
value
));
numstr
=
orgnum
=
int_to_roman
((
int
)
rint
(
value
));
}
else
{
float
32
val
=
value
;
float
4
val
=
value
;
if
(
IS_MULTI
(
&
Num
))
{
float
multi
=
pow
((
double
)
10
,
(
double
)
Num
.
multi
);
val
=
float4mul
(
value
,
(
float32
)
&
multi
)
;
val
=
value
*
multi
;
Num
.
pre
+=
Num
.
multi
;
}
orgnum
=
(
char
*
)
palloc
(
MAXFLOATWIDTH
+
1
);
len
=
sprintf
(
orgnum
,
"%.0f"
,
fabs
(
*
val
));
len
=
sprintf
(
orgnum
,
"%.0f"
,
fabs
(
val
));
if
(
Num
.
pre
>
len
)
plen
=
Num
.
pre
-
len
;
if
(
len
>=
FLT_DIG
)
Num
.
post
=
0
;
else
if
(
Num
.
post
+
len
>
FLT_DIG
)
Num
.
post
=
FLT_DIG
-
len
;
sprintf
(
orgnum
,
"%.*f"
,
Num
.
post
,
*
val
);
sprintf
(
orgnum
,
"%.*f"
,
Num
.
post
,
val
);
if
(
*
orgnum
==
'-'
)
{
/* < 0 */
...
...
@@ -4330,16 +4276,18 @@ float4_to_char(float32 value, text *fmt)
}
NUM_TOCHAR_finish
;
return
result
;
PG_RETURN_TEXT_P
(
result
)
;
}
/* -----------------
* FLOAT8 to_char()
* -----------------
*/
text
*
float8_to_char
(
float64
value
,
text
*
fmt
)
Datum
float8_to_char
(
PG_FUNCTION_ARGS
)
{
float8
value
=
PG_GETARG_FLOAT8
(
0
);
text
*
fmt
=
PG_GETARG_TEXT_P
(
1
);
NUMDesc
Num
;
FormatNode
*
format
;
text
*
result
,
...
...
@@ -4356,29 +4304,29 @@ float8_to_char(float64 value, text *fmt)
if
(
IS_ROMAN
(
&
Num
))
{
numstr
=
orgnum
=
int_to_roman
((
int
)
rint
(
*
value
));
numstr
=
orgnum
=
int_to_roman
((
int
)
rint
(
value
));
}
else
{
float
64
val
=
value
;
float
8
val
=
value
;
if
(
IS_MULTI
(
&
Num
))
{
double
multi
=
pow
((
double
)
10
,
(
double
)
Num
.
multi
);
val
=
float8mul
(
value
,
(
float64
)
&
multi
)
;
val
=
value
*
multi
;
Num
.
pre
+=
Num
.
multi
;
}
orgnum
=
(
char
*
)
palloc
(
MAXDOUBLEWIDTH
+
1
);
len
=
sprintf
(
orgnum
,
"%.0f"
,
fabs
(
*
val
));
len
=
sprintf
(
orgnum
,
"%.0f"
,
fabs
(
val
));
if
(
Num
.
pre
>
len
)
plen
=
Num
.
pre
-
len
;
if
(
len
>=
DBL_DIG
)
Num
.
post
=
0
;
else
if
(
Num
.
post
+
len
>
DBL_DIG
)
Num
.
post
=
DBL_DIG
-
len
;
sprintf
(
orgnum
,
"%.*f"
,
Num
.
post
,
*
val
);
sprintf
(
orgnum
,
"%.*f"
,
Num
.
post
,
val
);
if
(
*
orgnum
==
'-'
)
{
/* < 0 */
...
...
@@ -4407,5 +4355,5 @@ float8_to_char(float64 value, text *fmt)
}
NUM_TOCHAR_finish
;
return
result
;
PG_RETURN_TEXT_P
(
result
)
;
}
src/test/regress/expected/timestamp.out
View file @
e2252604
...
...
@@ -1023,7 +1023,7 @@ SELECT '' AS to_char_3, to_char(d1, 'Y,YYY YYYY YYY YY Y CC Q MM WW DDD DD D J')
|
|
|
| 1,970 1970 970 70 0 20 1 01 0
1
001 01 5 2440588
| 1,970 1970 970 70 0 20 1 01 0
0
001 01 5 2440588
| 1,997 1997 997 97 7 20 1 02 06 041 10 2 2450490
|
|
...
...
@@ -1032,8 +1032,8 @@ SELECT '' AS to_char_3, to_char(d1, 'Y,YYY YYYY YYY YY Y CC Q MM WW DDD DD D J')
| 1,997 1997 997 97 7 20 1 02 06 041 10 2 2450490
| 1,997 1997 997 97 7 20 1 02 06 041 10 2 2450490
| 1,997 1997 997 97 7 20 1 02 06 041 10 2 2450490
| 1,997 1997 997 97 7 20 1 01 0
1
002 02 5 2450451
| 1,997 1997 997 97 7 20 1 01 0
1
002 02 5 2450451
| 1,997 1997 997 97 7 20 1 01 0
0
002 02 5 2450451
| 1,997 1997 997 97 7 20 1 01 0
0
002 02 5 2450451
| 1,997 1997 997 97 7 20 1 02 06 041 10 2 2450490
| 1,997 1997 997 97 7 20 1 02 06 041 10 2 2450490
| 1,997 1997 997 97 7 20 1 02 06 041 10 2 2450490
...
...
@@ -1058,32 +1058,32 @@ SELECT '' AS to_char_3, to_char(d1, 'Y,YYY YYYY YYY YY Y CC Q MM WW DDD DD D J')
| 1,997 1997 997 97 7 20 2 06 23 161 10 3 2450610
| 1,997 1997 997 97 7 20 1 02 06 041 10 2 2450490
| 1,997 1997 997 97 7 20 1 02 06 042 11 3 2450491
| 1,997 1997 997 97 7 20 1 02 0
7
043 12 4 2450492
| 1,997 1997 997 97 7 20 1 02 0
7
044 13 5 2450493
| 1,997 1997 997 97 7 20 1 02 0
7
045 14 6 2450494
| 1,997 1997 997 97 7 20 1 02 0
7
046 15 7 2450495
| 1,997 1997 997 97 7 20 1 02 0
6
043 12 4 2450492
| 1,997 1997 997 97 7 20 1 02 0
6
044 13 5 2450493
| 1,997 1997 997 97 7 20 1 02 0
6
045 14 6 2450494
| 1,997 1997 997 97 7 20 1 02 0
6
046 15 7 2450495
| 1,997 1997 997 97 7 20 1 02 07 047 16 1 2450496
| 0,097 0097 097 97 7 01 1 02 07 047 16 3 1686042
| 0,097 0097 097 97 7 01 1 02 0
7
047 16 7 1756536
| 0,097 0097 097 97 7 01 1 02 0
6
047 16 7 1756536
| 0,597 0597 597 97 7 06 1 02 07 047 16 5 1939157
| 1,097 1097 097 97 7 11 1 02 07 047 16 3 2121778
| 1,697 1697 697 97 7 17 1 02 0
7
047 16 7 2340924
| 1,697 1697 697 97 7 17 1 02 0
6
047 16 7 2340924
| 1,797 1797 797 97 7 18 1 02 07 047 16 5 2377448
| 1,897 1897 897 97 7 19 1 02 07 047 16 3 2413972
| 1,997 1997 997 97 7 20 1 02 07 047 16 1 2450496
| 2,097 2097 097 97 7 21 1 02 0
7
047 16 7 2487021
| 2,097 2097 097 97 7 21 1 02 0
6
047 16 7 2487021
| 1,996 1996 996 96 6 20 1 02 09 059 28 4 2450142
| 1,996 1996 996 96 6 20 1 02 09 060 29 5 2450143
| 1,996 1996 996 96 6 20 1 03 09 061 01 6 2450144
| 1,996 1996 996 96 6 20 4 12 53 365 30 2 2450448
| 1,996 1996 996 96 6 20 4 12 53 366 31 3 2450449
| 1,997 1997 997 97 7 20 1 01 0
1
001 01 4 2450450
| 1,997 1997 997 97 7 20 1 02 0
9
059 28 6 2450508
| 1,997 1997 997 97 7 20 1 03 0
9
060 01 7 2450509
| 1,997 1997 997 97 7 20 1 01 0
0
001 01 4 2450450
| 1,997 1997 997 97 7 20 1 02 0
8
059 28 6 2450508
| 1,997 1997 997 97 7 20 1 03 0
8
060 01 7 2450509
| 1,997 1997 997 97 7 20 4 12 52 364 30 3 2450813
| 1,997 1997 997 97 7 20 4 12 5
3
365 31 4 2450814
| 1,999 1999 999 99 9 20 4 12 5
3
365 31 6 2451544
| 2,000 2000 000 00 0 21 1 01 0
1
001 01 7 2451545
| 1,997 1997 997 97 7 20 4 12 5
2
365 31 4 2450814
| 1,999 1999 999 99 9 20 4 12 5
2
365 31 6 2451544
| 2,000 2000 000 00 0 21 1 01 0
0
001 01 7 2451545
| 2,000 2000 000 00 0 21 4 12 53 366 31 1 2451910
| 2,001 2001 001 01 1 21 1 01 01 001 01 2 2451911
(66 rows)
...
...
@@ -1096,7 +1096,7 @@ SELECT '' AS to_char_4, to_char(d1, 'FMY,YYY FMYYYY FMYYY FMYY FMY FMCC FMQ FMMM
|
|
|
| 1,970 1970 970 70 0 20 1 1
1
1 1 5 2440588
| 1,970 1970 970 70 0 20 1 1
0
1 1 5 2440588
| 1,997 1997 997 97 7 20 1 2 6 41 10 2 2450490
|
|
...
...
@@ -1105,8 +1105,8 @@ SELECT '' AS to_char_4, to_char(d1, 'FMY,YYY FMYYYY FMYYY FMYY FMY FMCC FMQ FMMM
| 1,997 1997 997 97 7 20 1 2 6 41 10 2 2450490
| 1,997 1997 997 97 7 20 1 2 6 41 10 2 2450490
| 1,997 1997 997 97 7 20 1 2 6 41 10 2 2450490
| 1,997 1997 997 97 7 20 1 1
1
2 2 5 2450451
| 1,997 1997 997 97 7 20 1 1
1
2 2 5 2450451
| 1,997 1997 997 97 7 20 1 1
0
2 2 5 2450451
| 1,997 1997 997 97 7 20 1 1
0
2 2 5 2450451
| 1,997 1997 997 97 7 20 1 2 6 41 10 2 2450490
| 1,997 1997 997 97 7 20 1 2 6 41 10 2 2450490
| 1,997 1997 997 97 7 20 1 2 6 41 10 2 2450490
...
...
@@ -1131,32 +1131,32 @@ SELECT '' AS to_char_4, to_char(d1, 'FMY,YYY FMYYYY FMYYY FMYY FMY FMCC FMQ FMMM
| 1,997 1997 997 97 7 20 2 6 23 161 10 3 2450610
| 1,997 1997 997 97 7 20 1 2 6 41 10 2 2450490
| 1,997 1997 997 97 7 20 1 2 6 42 11 3 2450491
| 1,997 1997 997 97 7 20 1 2
7
43 12 4 2450492
| 1,997 1997 997 97 7 20 1 2
7
44 13 5 2450493
| 1,997 1997 997 97 7 20 1 2
7
45 14 6 2450494
| 1,997 1997 997 97 7 20 1 2
7
46 15 7 2450495
| 1,997 1997 997 97 7 20 1 2
6
43 12 4 2450492
| 1,997 1997 997 97 7 20 1 2
6
44 13 5 2450493
| 1,997 1997 997 97 7 20 1 2
6
45 14 6 2450494
| 1,997 1997 997 97 7 20 1 2
6
46 15 7 2450495
| 1,997 1997 997 97 7 20 1 2 7 47 16 1 2450496
| 0,097 97 097 97 7 1 1 2 7 47 16 3 1686042
| 0,097 97 097 97 7 1 1 2
7
47 16 7 1756536
| 0,097 97 097 97 7 1 1 2
6
47 16 7 1756536
| 0,597 597 597 97 7 6 1 2 7 47 16 5 1939157
| 1,097 1097 097 97 7 11 1 2 7 47 16 3 2121778
| 1,697 1697 697 97 7 17 1 2
7
47 16 7 2340924
| 1,697 1697 697 97 7 17 1 2
6
47 16 7 2340924
| 1,797 1797 797 97 7 18 1 2 7 47 16 5 2377448
| 1,897 1897 897 97 7 19 1 2 7 47 16 3 2413972
| 1,997 1997 997 97 7 20 1 2 7 47 16 1 2450496
| 2,097 2097 097 97 7 21 1 2
7
47 16 7 2487021
| 2,097 2097 097 97 7 21 1 2
6
47 16 7 2487021
| 1,996 1996 996 96 6 20 1 2 9 59 28 4 2450142
| 1,996 1996 996 96 6 20 1 2 9 60 29 5 2450143
| 1,996 1996 996 96 6 20 1 3 9 61 1 6 2450144
| 1,996 1996 996 96 6 20 4 12 53 365 30 2 2450448
| 1,996 1996 996 96 6 20 4 12 53 366 31 3 2450449
| 1,997 1997 997 97 7 20 1 1
1
1 1 4 2450450
| 1,997 1997 997 97 7 20 1 2
9
59 28 6 2450508
| 1,997 1997 997 97 7 20 1 3
9
60 1 7 2450509
| 1,997 1997 997 97 7 20 1 1
0
1 1 4 2450450
| 1,997 1997 997 97 7 20 1 2
8
59 28 6 2450508
| 1,997 1997 997 97 7 20 1 3
8
60 1 7 2450509
| 1,997 1997 997 97 7 20 4 12 52 364 30 3 2450813
| 1,997 1997 997 97 7 20 4 12 5
3
365 31 4 2450814
| 1,999 1999 999 99 9 20 4 12 5
3
365 31 6 2451544
| 2,000 2000 000 00 0 21 1 1
1
1 1 7 2451545
| 1,997 1997 997 97 7 20 4 12 5
2
365 31 4 2450814
| 1,999 1999 999 99 9 20 4 12 5
2
365 31 6 2451544
| 2,000 2000 000 00 0 21 1 1
0
1 1 7 2451545
| 2,000 2000 000 00 0 21 4 12 53 366 31 1 2451910
| 2,001 2001 001 01 1 21 1 1 1 1 1 2 2451911
(66 rows)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment