Back out Karels to_char changes.
authorBruce Momjian
Sat, 1 Jul 2000 21:27:14 +0000 (21:27 +0000)
committerBruce Momjian
Sat, 1 Jul 2000 21:27:14 +0000 (21:27 +0000)
doc/src/sgml/func.sgml
src/backend/utils/adt/formatting.c
src/test/regress/expected/timestamp.out

index 731f24902eb98d010c358aa59a1e27b6d6ade0b9..0023a28b0aa323100000525b626b6f778b03be94 100644 (file)
        
        
    W
-   week of month (1-5) where first week start on the first day of the month
+   week of month
         
        
    WW
-   week number of year (1-53) where first week start on the first day of the year
+   week number of year
        
        
    CC
      
       
        to_timestamp and to_date
-       skip multiple blank space in converted string if the FX option 
-       is not used. FX must be specified as the first item
-       in the template; for example 
-       to_timestamp('2000    JUN','YYYY MON') is right, but
-       to_timestamp('2000    JUN','FXYYYY MON') returns error,
-       because to_timestamp() expects one blank space only.
+       skip blank space if the FX option is
+       not used. FX must be specified as the first item
+       in the template.
       
      
 
index f7e38aaa137d95f4e339b5e6ce2e93e88dc3972b..be11b5300fb7bbe5e409ec5cab7ce154aaf65b7d 100644 (file)
@@ -1,8 +1,7 @@
-
 /* -----------------------------------------------------------------------
  * formatting.c
  *
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.15 2000/07/01 14:10:29 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/formatting.c,v 1.16 2000/07/01 21:27:11 momjian Exp $
  *
  *
  *  Portions Copyright (c) 1999-2000, PostgreSQL, Inc
 
 #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
  * External (defined in PgSQL dt.c (timestamp utils))
  * ----------
  */
-extern char    *months[],      /* month abbreviation   */
-       *days[];        /* full days        */
+extern char *months[],         /* month abbreviation   */
+          *days[];             /* full days        */
 
 /* ----------
  * Format parser structs
@@ -112,27 +114,27 @@ extern char   *months[],      /* month abbreviation   */
  */
 typedef struct
 {
-   char    *name;          /* suffix string        */
-   int len,            /* suffix length        */
-       id,         /* used in node->suffix */
-       type;           /* prefix / postfix         */
+   char       *name;           /* suffix string        */
+   int         len,            /* suffix length        */
+               id,             /* used in node->suffix */
+               type;           /* prefix / postfix         */
 } KeySuffix;
 
 typedef struct
 {
-   char    *name;          /* keyword          */
-                   /* action for keyword       */
-   int len,            /* keyword length       */
-       (*action) (),
-       id;         /* keyword id           */
+   char       *name;           /* keyword          */
+   /* action for keyword       */
+   int         len,            /* keyword length       */
+               (*action) (),
+               id;             /* keyword id           */
 } KeyWord;
 
 typedef struct
 {
-   int type;           /* node type            */
-   KeyWord *key;           /* if node type is KEYWORD  */
-   int character,      /* if node type is CHAR     */
-       suffix;         /* keyword suffix       */
+   int         type;           /* node type            */
+   KeyWord    *key;            /* if node type is KEYWORD  */
+   int         character,      /* if node type is CHAR     */
+               suffix;         /* keyword suffix       */
 } FormatNode;
 
 #define NODE_TYPE_END      1
@@ -232,12 +234,20 @@ 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
  * ----------
  */
-static int     DCH_global_flag = 0;
+static int DCH_global_flag = 0;
 
 #define DCH_F_FX   0x01
 
@@ -250,15 +260,15 @@ static int        DCH_global_flag = 0;
  */
 typedef struct
 {
-   int pre,        /* (count) numbers before decimal */
-       post,       /* (count) numbers after decimal  */
-       lsign,      /* want locales sign          */
-       flag,       /* number parametrs       */
-       pre_lsign_num,  /* tmp value for lsign        */
-       multi,      /* multiplier for 'V'         */
-       zero_start, /* position of first zero     */
-       zero_end,   /* position of last zero      */
-       need_locale;    /* needs it locale        */
+   int         pre,            /* (count) numbers before decimal */
+               post,           /* (count) numbers after decimal  */
+               lsign,          /* want locales sign          */
+               flag,           /* number parametrs       */
+               pre_lsign_num,  /* tmp value for lsign        */
+               multi,          /* multiplier for 'V'         */
+               zero_start,     /* position of first zero     */
+               zero_end,       /* position of last zero      */
+               need_locale;    /* needs it locale        */
 } NUMDesc;
 
 /* ----------
@@ -268,14 +278,14 @@ typedef struct
 #define NUM_F_DECIMAL  0x01
 #define NUM_F_LDECIMAL 0x02
 #define NUM_F_ZERO 0x04
-#define NUM_F_BLANK    0x08
+#define NUM_F_BLANK 0x08
 #define NUM_F_FILLMODE 0x10
-#define NUM_F_LSIGN    0x20
+#define NUM_F_LSIGN 0x20
 #define NUM_F_BRACKET  0x40
-#define NUM_F_MINUS    0x80
+#define NUM_F_MINUS 0x80
 #define NUM_F_PLUS 0x100
-#define NUM_F_ROMAN    0x200
-#define NUM_F_MULTI    0x400
+#define NUM_F_ROMAN 0x200
+#define NUM_F_MULTI 0x400
 
 #define NUM_LSIGN_PRE  -1
 #define NUM_LSIGN_POST 1
@@ -287,20 +297,20 @@ typedef struct
  */
 #define IS_DECIMAL(_f) ((_f)->flag & NUM_F_DECIMAL)
 #define IS_LDECIMAL(_f) ((_f)->flag & NUM_F_LDECIMAL)
-#define IS_ZERO(_f)    ((_f)->flag & NUM_F_ZERO)
+#define IS_ZERO(_f) ((_f)->flag & NUM_F_ZERO)
 #define IS_BLANK(_f)   ((_f)->flag & NUM_F_BLANK)
 #define IS_FILLMODE(_f) ((_f)->flag & NUM_F_FILLMODE)
 #define IS_BRACKET(_f) ((_f)->flag & NUM_F_BRACKET)
 #define IS_MINUS(_f)   ((_f)->flag & NUM_F_MINUS)
 #define IS_LSIGN(_f)   ((_f)->flag & NUM_F_LSIGN)
-#define IS_PLUS(_f)    ((_f)->flag & NUM_F_PLUS)
+#define IS_PLUS(_f) ((_f)->flag & NUM_F_PLUS)
 #define IS_ROMAN(_f)   ((_f)->flag & NUM_F_ROMAN)
 #define IS_MULTI(_f)   ((_f)->flag & NUM_F_MULTI)
 
 /* ----------
  * Format picture cache
  *     (cache size:
- *     Number part = NUM_CACHE_SIZE * NUM_CACHE_FIELDS
+ *     Number part     = NUM_CACHE_SIZE * NUM_CACHE_FIELDS
  *     Date-time part  = DCH_CACHE_SIZE * DCH_CACHE_FIELDS
  * )
  * ----------
@@ -314,14 +324,14 @@ typedef struct
 {
    FormatNode  format[DCH_CACHE_SIZE + 1];
    char        str[DCH_CACHE_SIZE + 1];
-   int     age;
+   int         age;
 } DCHCacheEntry;
 
 typedef struct
 {
    FormatNode  format[NUM_CACHE_SIZE + 1];
    char        str[NUM_CACHE_SIZE + 1];
-   int     age;
+   int         age;
    NUMDesc     Num;
 } NUMCacheEntry;
 
@@ -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" (1[0-9]) get 'TH/th',
+    * while [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,15 +1511,14 @@ dch_global(int arg, char *inout, int suf, int flag, FormatNode *node)
 {
    switch (arg)
    {
-       case DCH_FX:
-       DCH_global_flag |= DCH_F_FX;
-       break;
+
+           case DCH_FX:
+           DCH_global_flag |= DCH_F_FX;
+           break;
    }
    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_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", &tmfc->hh);
-                   return int4len((int4) tmfc->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", &tmfc->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", &tmfc->hh);
-                   return int4len((int4) tmfc->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", &tmfc->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", &tmfc->mi);
-                   return int4len((int4) tmfc->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", &tmfc->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", &tmfc->ss);
-                   return int4len((int4) tmfc->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", &tmfc->ss);
+                   sscanf(inout, "%02d", &tm->tm_sec);
                    return 1 + SKIP_THth(suf);
                }
            }
-           break;
        case DCH_SSSS:
            if (flag == TO_CHAR)
            {
@@ -1742,12 +1708,8 @@ dch_time(int arg, char *inout, int suf, int flag, FormatNode *node)
                    str_numth(p_inout, inout, S_TH_TYPE(suf));
                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;              
+           else if (flag == FROM_CHAR)
+               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));
@@ -1879,14 +1864,14 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
                return strlen(p_inout) - 1;
            else
                return 8;
-           
+
        case DCH_Month:
            sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, months_full[tm->tm_mon - 1]);
            if (S_FM(suf))
                return strlen(p_inout) - 1;
            else
                return 8;
-           
+
        case DCH_month:
            sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, months_full[tm->tm_mon - 1]);
            *inout = tolower(*inout);
@@ -1894,12 +1879,12 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
                return strlen(p_inout) - 1;
            else
                return 8;
-           
+
        case DCH_MON:
            strcpy(inout, months[tm->tm_mon - 1]);
            inout = str_toupper(inout);
            return 2;
-           
+
        case DCH_Mon:
            strcpy(inout, months[tm->tm_mon - 1]);
            return 2;
@@ -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", &tmfc->mm);
-                   return int4len((int4) tmfc->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", &tmfc->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", &tmfc->ddd);
-                   return int4len((int4) tmfc->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", &tmfc->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", &tmfc->dd);
-                   return int4len((int4) tmfc->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", &tmfc->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))
@@ -2051,20 +2040,8 @@ dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
                    return 1;
 
            }
-           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;  
+           else if (flag == FROM_CHAR)
+               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->yyyy);
-               tmfc->yyyy += (cc * 1000);
+               sscanf(inout, "%d,%03d", &cc, &yy);
+               tm->tm_year = (cc * 1000) + yy;
 
-               if (!S_FM(suf) && tmfc->yyyy <= 9999 && tmfc->yyyy >= -9999)
+               if (!S_FM(suf) && tm->tm_year <= 9999 && tm->tm_year >= -9999)
                    len = 5;
                else
-                   len = int4len((int4) tmfc->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", &tmfc->yyyy);
-               if (!S_FM(suf) && tmfc->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) tmfc->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)
            {
-               tmfc->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)
            {
-               tmfc->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");
@@ -2437,9 +2446,10 @@ timestamp_to_char(Timestamp *dt, text *fmt)
     * Allocate new memory if format picture is bigger than static cache
     * and not use cache (call parser always) - flag=1 show this variant
     * ----------
-    */
+        */
    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)
 {
-   FormatNode  *format;
-   int     flag = 0;
-   Timestamp   *result;
-   char        *str;
-   int     len = 0,
-           fsec = 0,
-           tz = 0,
-           x = 0;
-
-   if ((!PointerIsValid(date_str)) || (!PointerIsValid(fmt)))
-       return NULL;
-
-   result = palloc(sizeof(Timestamp));
-   len    = VARSIZE(fmt) - VARHDRSZ;
+   text       *date_str = PG_GETARG_TEXT_P(0);
+   text       *fmt = PG_GETARG_TEXT_P(1);
+   FormatNode *format;
+   int         flag = 0;
+   Timestamp   result;
+   char       *str;
+   int         len = 0,
+               fsec = 0,
+               tz = 0;
+
+   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;
 
-   ZERO_tmfc(tmfc);
+   len = VARSIZE(fmt) - VARHDRSZ;
 
    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'
  * ----------
  */
-DateADT
-to_date(text *date_str, text *fmt)
+Datum
+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
    {
-       float32     val = value;
+       float     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
    {
-       float64     val = value;
+       float     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);
 }
index 15120b87587a3bad14f186cb8f1774355f4ac1cb..72c02b1fa2f08e6c1dded3273a8aa213b0b756f7 100644 (file)
@@ -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 01 001 01 5 2440588
+           | 1,970 1970 970 70 0 20 1 01 00 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 01 002 02 5 2450451
-           | 1,997 1997 997 97 7 20 1 01 01 002 02 5 2450451
+           | 1,997 1997 997 97 7 20 1 01 00 002 02 5 2450451
+           | 1,997 1997 997 97 7 20 1 01 00 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 07 043 12 4 2450492
-           | 1,997 1997 997 97 7 20 1 02 07 044 13 5 2450493
-           | 1,997 1997 997 97 7 20 1 02 07 045 14 6 2450494
-           | 1,997 1997 997 97 7 20 1 02 07 046 15 7 2450495
+           | 1,997 1997 997 97 7 20 1 02 06 043 12 4 2450492
+           | 1,997 1997 997 97 7 20 1 02 06 044 13 5 2450493
+           | 1,997 1997 997 97 7 20 1 02 06 045 14 6 2450494
+           | 1,997 1997 997 97 7 20 1 02 06 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 07 047 16 7 1756536
+           | 0,097 0097 097 97 7 01 1 02 06 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 07 047 16 7 2340924
+           | 1,697 1697 697 97 7 17 1 02 06 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 07 047 16 7 2487021
+           | 2,097 2097 097 97 7 21 1 02 06 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 01 001 01 4 2450450
-           | 1,997 1997 997 97 7 20 1 02 09 059 28 6 2450508
-           | 1,997 1997 997 97 7 20 1 03 09 060 01 7 2450509
+           | 1,997 1997 997 97 7 20 1 01 00 001 01 4 2450450
+           | 1,997 1997 997 97 7 20 1 02 08 059 28 6 2450508
+           | 1,997 1997 997 97 7 20 1 03 08 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 53 365 31 4 2450814
-           | 1,999 1999 999 99 9 20 4 12 53 365 31 6 2451544
-           | 2,000 2000 000 00 0 21 1 01 01 001 01 7 2451545
+           | 1,997 1997 997 97 7 20 4 12 52 365 31 4 2450814
+           | 1,999 1999 999 99 9 20 4 12 52 365 31 6 2451544
+           | 2,000 2000 000 00 0 21 1 01 00 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 53 365 31 4 2450814
-           | 1,999 1999 999 99 9 20 4 12 53 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 52 365 31 4 2450814
+           | 1,999 1999 999 99 9 20 4 12 52 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)