summaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
authorBruce Momjian2000-01-25 23:53:56 +0000
committerBruce Momjian2000-01-25 23:53:56 +0000
commitb866d2e2d79416f8497e4dffa7e800298d018f6c (patch)
treeb633b1415e4b916aaff71d86dc8cee4dba0258e9 /contrib
parent90aaad06cf25753e10717ac7eb727cd65d8d5726 (diff)
as attache of this mail is patch (to the main tree) with to_char's
family functions. Contain: conversion from a datetype to formatted text: to_char( datetime, text) to_char( timestamp, text) to_char( int4, text) to_char( int8, text) to_char( float4, text) to_char( float8, text) to_char( numeric, text) vice versa: to_date ( text, text) to_datetime ( text, text) to_timestamp ( text, text) to_number ( text, text) (convert to numeric) PostgreSQL to_char is very compatible with Oracle's to_char(), but not total exactly (now). Small differentions are in number formating. It will fix in next to_char() version. ! If will this patch aplly to the main tree, must be delete the current to_char version in contrib (directory "dateformat" and note in contrib's README), this patch not erase it (sorry Bruce). The patch patching files: doc/src/sgml/func.sgml ^^^^^^^^ Hmm, I'm not sure if my English... :( Check it anyone (volunteer)? Thomas, it is right? SGML is not my primary lang and compile the current PG docs tree is very happy job (hard variables setting in docs/sgml/Makefile --> HSTYLE= /home/users/t/thomas/.... :-) What add any definition to global configure.in and set Makefiles in docs tree via ./configure? src/backend/utils/adt/Makefile src/backend/utils/adt/formatting.c src/include/catalog/pg_proc.h src/include/utils/formatting.h Karel Zak <zakkr@zf.jcu.cz> http://home.zf.jcu.cz/~zakkr/
Diffstat (limited to 'contrib')
-rw-r--r--contrib/README4
-rw-r--r--contrib/dateformat/Makefile71
-rw-r--r--contrib/dateformat/test/Makefile25
-rw-r--r--contrib/dateformat/test/README33
-rw-r--r--contrib/dateformat/test/rand_datetime.c71
-rw-r--r--contrib/dateformat/test/regress.sql58
-rw-r--r--contrib/dateformat/to-from_char.c1382
-rw-r--r--contrib/dateformat/to-from_char.doc183
-rw-r--r--contrib/dateformat/to-from_char.h18
-rw-r--r--contrib/dateformat/to-from_char.sql.in29
10 files changed, 0 insertions, 1874 deletions
diff --git a/contrib/README b/contrib/README
index 5b1a4600f78..0fcaa468f26 100644
--- a/contrib/README
+++ b/contrib/README
@@ -14,10 +14,6 @@ bit -
Bit type
by Adriaan Joubert <a.joubert@albourne.com>
-dateformat -
- Date Formatting to/from character strings
- by Karel Zak - Zakkr <zakkr@zf.jcu.cz>
-
datetime -
Date & time functions
by Massimo Dal Zotto <dz@cs.unitn.it>
diff --git a/contrib/dateformat/Makefile b/contrib/dateformat/Makefile
deleted file mode 100644
index 849d7a777e2..00000000000
--- a/contrib/dateformat/Makefile
+++ /dev/null
@@ -1,71 +0,0 @@
-#-------------------------------------------------------------------------
-#
-# Makefile --
-#
-# Makefile for TO-FROM_CHAR module.
-#
-#-------------------------------------------------------------------------
-
-PGDIR = ../..
-SRCDIR = $(PGDIR)/src
-
-include $(SRCDIR)/Makefile.global
-
-INCLUDE_OPT = -I ./ \
- -I $(SRCDIR)/ \
- -I $(SRCDIR)/include \
- -I $(SRCDIR)/port/$(PORTNAME)
-
-CFLAGS += $(INCLUDE_OPT) $(CFLAGS_SL)
-
-MODNAME = to-from_char
-
-SQLDEFS = $(MODNAME).sql
-
-MODULE = $(MODNAME)$(DLSUFFIX)
-
-MODDIR = $(LIBDIR)/modules
-
-SQLDIR = $(LIBDIR)/sql
-
-all: module sql
-
-module: $(MODULE)
-
-sql: $(SQLDEFS)
-
-install: $(MODULE) $(SQLDEFS) $(MODDIR) $(SQLDIR)
- cp -p $(MODULE) $(MODDIR)/
- strip $(MODDIR)/$(MODULE)
- cp -p $(SQLDEFS) $(SQLDIR)/
-
-install-doc:
- if [ -d "$(DOCDIR)" ]; then \
- cp -p *.doc $(DOCDIR); \
- else \
- cp -p *.doc $(SQLDIR); \
- fi
-
-$(MODDIR):
- mkdir -p $@
-
-$(SQLDIR):
- mkdir -p $@
-
-%.sql: %.sql.in
- sed "s|MODULE_PATHNAME|$(MODDIR)/$(MODULE)|" < $< > $@
-
-.SUFFIXES: $(DLSUFFIX)
-
-%$(DLSUFFIX): %.c
- $(CC) $(CFLAGS) -shared -o $@ $<
-
-depend dep:
- $(CC) -MM $(INCLUDE_OPT) *.c >depend
-
-clean:
- rm -f *~ $(MODULE) $(MODNAME).sql
-
-ifeq (depend,$(wildcard depend))
-include depend
-endif
diff --git a/contrib/dateformat/test/Makefile b/contrib/dateformat/test/Makefile
deleted file mode 100644
index 6eb539c3aa5..00000000000
--- a/contrib/dateformat/test/Makefile
+++ /dev/null
@@ -1,25 +0,0 @@
-
-PROGRAM = rand_datetime
-
-OBJECTS = rand_datetime.o
-
-CFLAGS = -Wall -fpic -O3
-CC = gcc
-RM = rm -f
-LIBS =
-INCLUDE =
-
-COMPILE = $(CC) $(CPPFLAGS) $(CFLAGS) $(INCLUDE)
-LINK = $(CC) $(CFLAGS) -o $@ $(LIBS)
-
-
-all: $(PROGRAM)
-
-$(PROGRAM): $(OBJECTS)
- $(LINK) $(OBJECTS)
-
-.c.o: $<
- $(COMPILE) -c $<
-
-clean:
- $(RM) -f *~ $(OBJECTS) $(PROGRAM)
diff --git a/contrib/dateformat/test/README b/contrib/dateformat/test/README
deleted file mode 100644
index 63177f2ee52..00000000000
--- a/contrib/dateformat/test/README
+++ /dev/null
@@ -1,33 +0,0 @@
-
- TO/FROM CHAR tests
- ~~~~~~~~~~~~~~~~~~
-
- * rand_datetime
-
- The program 'rand_datetime' output a random datetime strings
- (with yaer range 0..9999), you can use this for datetime testing.
-
- You can usage this (example) for table filling.
-
- Usage:
-
- ./rand_datetime <randfile> <num> <prefix> <postfix>
-
- Example:
-
- ./rand_datetime /dev/urandom 2 "INSERT INTO tab VALUES('" "'::datetime);"
-
- INSERT INTO tab VALUES('Sat 27 Jul 13:08:57 19618'::datetime);
- INSERT INTO tab VALUES('Wed 25 Aug 20:31:50 27450'::datetime);
-
- * regress
-
- psql < regress.sql (all answers, must be TRUE, for Posgres
- datestyle)
-
-
- --> TO_DATE() is simular as FROM_CHAR(), but convert full datetime
- to date ==> needn't test (?).
-
-
-
diff --git a/contrib/dateformat/test/rand_datetime.c b/contrib/dateformat/test/rand_datetime.c
deleted file mode 100644
index 6a96776b9b7..00000000000
--- a/contrib/dateformat/test/rand_datetime.c
+++ /dev/null
@@ -1,71 +0,0 @@
-
-#include <stdio.h>
-#include <errno.h>
-#include <ctype.h>
-#include <stdlib.h>
-
-
-char *month[] = {
- "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec",NULL
-};
-
-char *day[] = { "Sun","Mon","Tue","Wed","Thu","Fri","Sat", NULL };
-
-int num(FILE *f, int min, int max)
-{
- int x, y, one;
-
- one = x = fgetc(f);
-
-
- if (x < min)
- x = min;
- else if (x > max) {
- while(x > max)
- x /= 2;
- return x;
- }
-
- do {
- y = fgetc(f);
- if ((x+y) > max)
- return x;
- x += y;
- } while(--one > 0);
-
- return x;
-}
-
-int main(int argc, char **argv)
-{
- FILE *f;
- int count;
-
- if (argc < 5) {
- printf("\nUsage: %s <randfile> <num> <prefix> <postfix>\n", argv[0]);
- printf("\n(C) Karel Zak - Zakkr 1999\n\n");
- exit(1);
- }
-
- if ((f = fopen(argv[1], "r")) == NULL) {
- perror(argv[1]);
- exit(1);
- }
-
- count = atoi(argv[2]);
-
- for(; count > 0; --count) {
- fprintf(stdout, "%s%s %02d %s %02d:%02d:%02d %d%s\n",
- argv[3],
- day[ num(f, 0, 6) ],
- num(f, 1, 28),
- month[ num(f, 0, 11) ],
- num(f, 0, 23),
- num(f, 0, 59),
- num(f, 0, 59),
- num(f, 0, 9999),
- argv[4]
- );
- }
- exit(0);
-} \ No newline at end of file
diff --git a/contrib/dateformat/test/regress.sql b/contrib/dateformat/test/regress.sql
deleted file mode 100644
index f3c2815fab3..00000000000
--- a/contrib/dateformat/test/regress.sql
+++ /dev/null
@@ -1,58 +0,0 @@
-
----
---- Postgres DateStyle needs all tests which parsing 'now'::datetime string
----
-SET DATESTYLE TO 'Postgres';
-
-
-SELECT 'now'::datetime =
- TO_CHAR('now'::datetime, 'Dy Mon DD HH24:MI:SS YYYY')::datetime
-as "Now vs. to_char";
-
-
-SELECT 'now'::datetime =
- FROM_CHAR('now'::datetime, 'Dy Mon DD HH24:MI:SS YYYY')
-as "Now vs. from_char";
-
-
-SELECT FROM_CHAR('now'::datetime, 'Dy Mon DD HH24:MI:SS YYYY') =
- TO_CHAR('now'::datetime, 'Dy Mon DD HH24:MI:SS YYYY')::datetime
-as "From_char vs. To_char";
-
-
-SELECT 'now'::datetime =
- FROM_CHAR(
- TO_CHAR('now'::datetime, '"Time: "HH24-MI-SS" Date: "Dy DD Mon YYYY'),
- '"Time: "HH24-MI-SS" Date: "Dy DD Mon YYYY'
- )
-as "High from/to char test";
-
-
-SELECT TO_CHAR('now'::datetime, 'SSSS')::int =
- TO_CHAR('now'::datetime, 'HH24')::int * 3600 +
- TO_CHAR('now'::datetime, 'MI')::int * 60 +
- TO_CHAR('now'::datetime, 'SS')::int
-as "SSSS test";
-
-
-SELECT TO_CHAR('now'::datetime, 'WW')::int =
- (TO_CHAR('now'::datetime, 'DDD')::int -
- TO_CHAR('now'::datetime, 'D')::int + 7) / 7
-as "Week test";
-
-
-SELECT TO_CHAR('now'::datetime, 'Q')::int =
- TO_CHAR('now'::datetime, 'MM')::int / 3 + 1
-as "Quartal test";
-
-
-SELECT TO_CHAR('now'::datetime, 'DDD')::int =
- (TO_CHAR('now'::datetime, 'WW')::int * 7) -
- (7 - TO_CHAR('now'::datetime, 'D')::int) +
- (7 - TO_CHAR(('01-Jan-'||
- TO_CHAR('now'::datetime,'YYYY'))::datetime,'D')::int)
- +1
-as "Week and day test";
-
-
-
diff --git a/contrib/dateformat/to-from_char.c b/contrib/dateformat/to-from_char.c
deleted file mode 100644
index eebd7a8c642..00000000000
--- a/contrib/dateformat/to-from_char.c
+++ /dev/null
@@ -1,1382 +0,0 @@
-
-/******************************************************************
- *
- * The PostgreSQL modul for DateTime formating, inspire with
- * Oracle TO_CHAR() / TO_DATE() routines.
- *
- * Copyright (c) 1999, Karel Zak "Zakkr" <zakkr@zf.jcu.cz>
- *
- * This file is distributed under the GNU General Public License
- * either version 2, or (at your option) any later version.
- *
- *
- * NOTE:
- * In this modul is _not_ used POSIX 'struct tm' type, but
- * PgSQL type, which has tm_mon based on one (_non_ zero) and
- * year not based on 1900, but is used full year number.
- * Modul support AC / BC years.
- *
- ******************************************************************/
-
-/*
-#define DEBUG_TO_FROM_CHAR
-#define DEBUG_elog_output NOTICE
-*/
-
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/time.h>
-#include <unistd.h>
-
-#include "postgres.h"
-#include "utils/builtins.h"
-
-#include "to-from_char.h"
-
-#define MAX_NODE_SIZ 16 /* maximal length of one node */
-
-#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
-
-/*------
- * (External) defined in PgSQL dt.c (datetime utils)
- *------
- */
-extern char *months[], /* month abbreviation */
- *days[]; /* full days */
-
-/*------
- * Private definitions
- *------
- */
-static struct tm _tm, *tm = &_tm;
-
-static char *months_full[] = {
- "January", "February", "March", "April", "May", "June", "July",
- "August", "September", "October", "November", "December", NULL
-};
-
-/*------
- * AC / DC
- *------
- */
-#define YEAR_ABS(_y) (_y < 0 ? -(_y -1) : _y)
-#define BC_STR " BC"
-
-/*------
- * Months in roman-numeral
- * (Must be conversely for seq_search (in FROM_CHAR), because
- * 'VIII' must be over 'V')
- *------
- */
-static char *rm_months[] = {
- "XII", "XI", "X", "IX", "VIII", "VII",
- "VI", "V", "IV", "III", "II", "I", NULL
-};
-
-/*------
- * Ordinal postfixes
- *------
- */
-static char *numTH[] = { "ST", "ND", "RD", "TH", NULL };
-static char *numth[] = { "st", "nd", "rd", "th", NULL };
-
-/*------
- * Flags:
- *------
- */
-#define TO_CHAR 1
-#define FROM_CHAR 2
-
-#define ONE_UPPER 1 /* Name */
-#define ALL_UPPER 2 /* NAME */
-#define ALL_LOWER 3 /* name */
-
-#define FULL_SIZ 0
-
-#define MAX_MON_LEN 3
-#define MAX_DY_LEN 3
-
-#define TH_UPPER 1
-#define TH_LOWER 2
-
-/****************************************************************************
- * Structs for format parsing
- ****************************************************************************/
-
-/*------
- * Format parser structs
- *------
- */
-typedef struct {
- 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 */
-} KeyWord;
-
-typedef struct {
- 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 0
-#define NODE_TYPE_ACTION 1
-#define NODE_TYPE_CHAR 2
-#define NODE_LAST 3 /* internal option */
-
-#define SUFFTYPE_PREFIX 1
-#define SUFFTYPE_POSTFIX 2
-
-
-/*****************************************************************************
- * KeyWords definition & action
- *****************************************************************************/
-
-static int dch_time(int arg, char *inout, int suf, int flag, FormatNode *node);
-static int dch_date(int arg, char *inout, int suf, int flag, FormatNode *node);
-
-/*------
- * Suffixes:
- *------
- */
-#define DCH_S_FM 0x01
-#define DCH_S_TH 0x02
-#define DCH_S_th 0x04
-#define DCH_S_SP 0x08
-
-/*------
- * Suffix tests
- *------
- */
-#define S_THth(_s) (((_s & DCH_S_TH) || (_s & DCH_S_th)) ? 1 : 0)
-#define S_TH(_s) ((_s & DCH_S_TH) ? 1 : 0)
-#define S_th(_s) ((_s & DCH_S_th) ? 1 : 0)
-#define S_TH_TYPE(_s) ((_s & DCH_S_TH) ? TH_UPPER : TH_LOWER)
-
-#define S_FM(_s) ((_s & DCH_S_FM) ? 1 : 0)
-#define S_SP(_s) ((_s & DCH_S_SP) ? 1 : 0)
-
-/*------
- * Suffixes definition for TO / FROM CHAR
- *------
- */
-static KeySuffix suff[] = {
- { "FM", 2, DCH_S_FM, SUFFTYPE_PREFIX },
- { "TH", 2, DCH_S_TH, SUFFTYPE_POSTFIX },
- { "th", 2, DCH_S_th, SUFFTYPE_POSTFIX },
- { "SP", 2, DCH_S_SP, SUFFTYPE_POSTFIX },
- /* last */
- { NULL, 0, 0, 0 }
-};
-
-/*------
- *
- * The KeyWord field; alphabetic sorted, *BUT* strings alike is sorted
- * complicated -to-> easy:
- *
- * (example: "DDD","DD","Day","D" )
- *
- * (this specific sort needs the algorithm for sequential search for strings,
- * which not has exact end; - How keyword is in "HH12blabla" ? - "HH"
- * or "HH12"? You must first try "HH12", because "HH" is in string, but
- * it is not good:-)
- *
- * (!) Position for the keyword is simular as position in the enum I_poz (!)
- *
- * For fast search is used the KWindex[256], in this index is DCH_ enums for
- * each ASCII position or -1 if char is not used in the KeyWord. Search example
- * for string "MM":
- * 1) see KWindex to KWindex[77] ('M'),
- * 2) take keywords position from KWindex[77]
- * 3) run sequential search in keywords[] from position
- *
- *------
- */
-
-typedef enum {
- DCH_CC,
- DCH_DAY,
- DCH_DDD,
- DCH_DD,
- DCH_DY,
- DCH_Day,
- DCH_Dy,
- DCH_D,
- DCH_HH24,
- DCH_HH12,
- DCH_HH,
- DCH_J,
- DCH_MI,
- DCH_MM,
- DCH_MONTH,
- DCH_MON,
- DCH_Month,
- DCH_Mon,
- DCH_Q,
- DCH_RM,
- DCH_SSSS,
- DCH_SS,
- DCH_WW,
- DCH_W,
- DCH_Y_YYY,
- DCH_YYYY,
- DCH_YYY,
- DCH_YY,
- DCH_Y,
- DCH_day,
- DCH_dy,
- DCH_month,
- DCH_mon,
- /* last */
- _DCH_last_
-} I_poz;
-
-static KeyWord keywords[] = {
-/* keyword, len, func. I_poz is in KWindex */
-
-{ "CC", 2, dch_date, DCH_CC }, /*C*/
-{ "DAY", 3, dch_date, DCH_DAY }, /*D*/
-{ "DDD", 3, dch_date, DCH_DDD },
-{ "DD", 2, dch_date, DCH_DD },
-{ "DY", 2, dch_date, DCH_DY },
-{ "Day", 3, dch_date, DCH_Day },
-{ "Dy", 2, dch_date, DCH_Dy },
-{ "D", 1, dch_date, DCH_D },
-{ "HH24", 4, dch_time, DCH_HH24 }, /*H*/
-{ "HH12", 4, dch_time, DCH_HH12 },
-{ "HH", 2, dch_time, DCH_HH },
-{ "J", 1, dch_date, DCH_J }, /*J*/
-{ "MI", 2, dch_time, DCH_MI },
-{ "MM", 2, dch_date, DCH_MM },
-{ "MONTH", 5, dch_date, DCH_MONTH },
-{ "MON", 3, dch_date, DCH_MON },
-{ "Month", 5, dch_date, DCH_Month },
-{ "Mon", 3, dch_date, DCH_Mon },
-{ "Q", 1, dch_date, DCH_Q }, /*Q*/
-{ "RM", 2, dch_date, DCH_RM }, /*R*/
-{ "SSSS", 4, dch_time, DCH_SSSS }, /*S*/
-{ "SS", 2, dch_time, DCH_SS },
-{ "WW", 2, dch_date, DCH_WW }, /*W*/
-{ "W", 1, dch_date, DCH_W },
-{ "Y,YYY", 5, dch_date, DCH_Y_YYY }, /*Y*/
-{ "YYYY", 4, dch_date, DCH_YYYY },
-{ "YYY", 3, dch_date, DCH_YYY },
-{ "YY", 2, dch_date, DCH_YY },
-{ "Y", 1, dch_date, DCH_Y },
-{ "day", 3, dch_date, DCH_day }, /*d*/
-{ "dy", 2, dch_date, DCH_dy },
-{ "month", 5, dch_date, DCH_month }, /*m*/
-{ "mon", 3, dch_date, DCH_mon },
-/* last */
-{ NULL, 0, NULL, 0 }};
-
-
-static int KWindex[256] = {
-/*
-0 1 2 3 4 5 6 7 8 9
-*/
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
--1, -1, -1, -1, -1, -1, -1, DCH_CC, DCH_DAY,-1,
--1, -1, DCH_HH24,-1, DCH_J, -1, -1, DCH_MI, -1, -1,
--1, DCH_Q, DCH_RM, DCH_SSSS,-1, -1, -1, DCH_WW, -1, DCH_Y_YYY,
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-DCH_day,-1, -1, -1, -1, -1, -1, -1, -1, DCH_month,
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
--1, -1, -1, -1, -1, -1
-};
-
-
-/*------
- * Fast sequential search, use index for selection data which
- * go to seq. cycle (it is very fast for non-wanted strings)
- * (can't be used binary search in format parsing)
- *------
- */
-static KeyWord *index_seq_search(char *str, KeyWord *kw, int *index)
-{
- int poz;
-
- if ( (poz = *(index + *str)) > -1) {
-
- KeyWord *k = kw+poz;
-
- do {
- if (! strncmp(str, k->name, k->len))
- return k;
- k++;
- if (!k->name)
- return (KeyWord *) NULL;
- } while(*str == *k->name);
- }
- return (KeyWord *) NULL;
-}
-
-static KeySuffix *suff_search(char *str, KeySuffix *suf, int type)
-{
- KeySuffix *s;
-
- for(s=suf; s->name != NULL; s++) {
- if (s->type != type)
- continue;
-
- if (!strncmp(str, s->name, s->len))
- return s;
- }
- return (KeySuffix *) NULL;
-}
-
-/*------
- * Format parser, search small keywords and keyword's suffixes, and make
- * format-node tree.
- *------
- */
-#undef FUNC_NAME
-#define FUNC_NAME "parse_format"
-
-static void parse_format(FormatNode *node, char *str, KeyWord *kw,
- KeySuffix *suf, int *index)
-{
- KeySuffix *s;
- FormatNode *n;
- int node_set=0,
- suffix,
- last=0;
- n = node;
-
- while(*str) {
- suffix=0;
-
- /* prefix */
- if ((s = suff_search(str, suf, SUFFTYPE_PREFIX)) != NULL) {
- suffix |= s->id;
- if (s->len)
- str += s->len;
- }
-
- /* keyword */
- if (*str && (n->key = index_seq_search(str, kw, index)) != NULL) {
- n->type = NODE_TYPE_ACTION;
- n->suffix = 0;
- node_set= 1;
- if (n->key->len)
- str += n->key->len;
-
- /* postfix */
- if (*str && (s = suff_search(str, suf, SUFFTYPE_POSTFIX)) != NULL) {
- suffix |= s->id;
- if (s->len)
- str += s->len;
- }
-
- } else if (*str) {
- /* special characters '\' and '"' */
-
- if (*str == '"' && last != '\\') {
- while(*(++str)) {
- if (*str == '"') {
- str++;
- break;
- }
- n->type = NODE_TYPE_CHAR;
- n->character = *str;
- n->key = (KeyWord *) NULL;
- n->suffix = 0;
- ++n;
- }
- node_set = 0;
- suffix = 0;
- last = 0;
-
- } else if (*str && *str == '\\' && last!='\\' && *(str+1) =='"') {
- last = *str;
- str++;
-
- } else if (*str) {
- n->type = NODE_TYPE_CHAR;
- n->character = *str;
- n->key = (KeyWord *) NULL;
- node_set = 1;
- last = 0;
- str++;
- }
- }
-
- /* end */
- if (node_set) {
- if (n->type == NODE_TYPE_ACTION)
- n->suffix = suffix;
- ++n;
- n->suffix = 0;
- node_set = 0;
- }
- }
-
- n->type = NODE_TYPE_END;
- n->suffix = 0;
- return;
-}
-
-/*------
- * Call keyword's function for each of (action) node in format-node tree
- *------
- */
-static char *node_action(FormatNode *node, char *inout, int flag)
-{
- FormatNode *n;
- char *s;
-
- for(n=node, s=inout; n->type != NODE_TYPE_END; n++, s++) {
- if (n->type == NODE_TYPE_ACTION) {
-
- int len;
-
- /*
- * Call node action function
- */
- len = n->key->action(n->key->id, s, n->suffix, flag, n);
- if (len > 0)
- s += len;
-
- } else {
-
- /*
- * Remove to output char from input in TO_CHAR
- */
- if (flag == TO_CHAR)
- *s = n->character;
-
- else {
- /*
- * Skip blank space in FROM_CHAR's input
- */
- if (isspace(n->character)) {
- while(*s != '\0' && isspace(*(s+1)))
- ++s;
- }
- }
- }
- }
-
- if (flag == TO_CHAR)
- *s = '\0';
- return inout;
-}
-
-/*****************************************************************************
- * Private utils
- *****************************************************************************/
-
-/*------
- * Return ST/ND/RD/TH for simple (1..9) numbers
- * type --> 0 upper, 1 lower
- *------
- */
-static char *get_th(int num, int type)
-{
- switch(num) {
- case 1:
- if (type==TH_UPPER) return numTH[0];
- return numth[0];
- case 2:
- if (type==TH_UPPER) return numTH[1];
- return numth[1];
- case 3:
- if (type==TH_UPPER) return numTH[2];
- return numth[2];
- }
- if (type==TH_UPPER) return numTH[3];
- return numth[3];
-}
-
-/*------
- * Convert string-number to ordinal string-number
- * type --> 0 upper, 1 lower
- *------
- */
-#undef FUNC_NAME
-#define FUNC_NAME "str_numth"
-
-static char *str_numth(char *dest, char *src, int type)
-{
- int len = strlen(src),
- num=0, f_num=0;
-
- num = *(src+(len-1));
- if (num < 48 || num > 57)
- elog(ERROR, "%s: in '%s' is not number.", FUNC_NAME, src);
-
- num -= 48;
- if (num==1 || num==2) { /* 11 || 12 */
- f_num = atoi(src);
- if (abs(f_num)==11 || abs(f_num)==12)
- num=0;
- }
- sprintf(dest, "%s%s", src, get_th(num, type));
- return dest;
-}
-
-/*------
- * Return length of integer writed in string
- *-------
- */
-static int int4len(int4 num)
-{
- char b[16];
-
- sprintf(b, "%d", num);
- return strlen(b);
-}
-
-/*------
- * Convert string to upper-string
- *------
- */
-static char *str_toupper(char *buff)
-{
- char *p_buff=buff;
-
- while (*p_buff) {
- *p_buff = toupper((unsigned char) *p_buff);
- ++p_buff;
- }
- return buff;
-}
-
-/*------
- * Check if in string is AC or BC (return: 0==none; -1==BC; 1==AC)
- *------
- */
-static int is_acdc(char *str, int *len)
-{
- char *p;
-
- for(p=str; *p != '\0'; p++) {
- if (isspace(*p))
- continue;
-
- if (*(p+1)) {
- if (toupper(*p)=='B' && toupper(*(++p))=='C') {
- *len += (p - str) +1;
- return -1;
- } else if (toupper(*p)=='A' && toupper(*(++p))=='C') {
- *len += (p - str) +1;
- return 1;
- }
- }
- return 0;
- }
- return 0;
-}
-
-
-/*------
- * Sequential search with to upper/lower conversion
- *------
- */
-static int seq_search(char *name, char **array, int type, int max, int *len)
-{
- char *p, *n, **a;
- int last, i;
-
- *len = 0;
-
- if (!*name)
- return -1;
-
- /* set first char */
- if (type == ONE_UPPER || ALL_UPPER)
- *name = toupper((unsigned char) *name);
- else if (type == ALL_LOWER)
- *name = tolower((unsigned char) *name);
-
- for(last=0, a=array; *a != NULL; a++) {
-
- /* comperate first chars */
- if (*name != **a)
- continue;
-
- for(i=1, p=*a+1, n=name+1; ; n++, p++, i++) {
-
- /* search fragment (max) only */
- if (max && i == max) {
- *len = i;
- return a - array;
- }
- /* full size */
- if (*p=='\0') {
- *len = i;
- return a - array;
- }
- /* Not found in array 'a' */
- if (*n=='\0')
- break;
-
- /*
- * Convert (but convert new chars only)
- */
- if (i > last) {
- if (type == ONE_UPPER || type == ALL_LOWER)
- *n = tolower((unsigned char) *n);
- else if (type == ALL_UPPER)
- *n = toupper((unsigned char) *n);
- last=i;
- }
-
-#ifdef DEBUG_TO_FROM_CHAR
- elog(DEBUG_elog_output, "N: %c, P: %c, A: %s (%s)", *n, *p, *a, name);
-#endif
-
- if (*n != *p)
- break;
- }
- }
-
- return -1;
-}
-
-
-#ifdef DEBUG_TO_FROM_CHAR
-/*-------
- * Call for debug and for KWindex checking; (Show ASCII char and defined
- * keyword for each used position
- *-------
- */
-static void dump_KWindex()
-{
- int i;
-
- for(i=0; i<255; i++) {
- if (KWindex[i] != -1)
- elog(NOTICE, "%c: %s, ", i, keywords[ KWindex[i] ].name);
- }
-}
-#endif
-
-/*****************************************************************************
- * Master routines
- *****************************************************************************/
-
-/*
- * Spip TM / th in FROM_CHAR
- */
-#define SKIP_THth(_suf) (S_THth(_suf) ? 2 : 0)
-
-/*------
- * Master of TIME for TO_CHAR - write (inout) formated string
- * FROM_CHAR - scan (inout) string by course of FormatNode
- *------
- */
-#undef FUNC_NAME
-#define FUNC_NAME "dch_time"
-
-static int dch_time(int arg, char *inout, int suf, int flag, FormatNode *node)
-{
- char *p_inout = inout;
-
- switch(arg) {
- case DCH_HH:
- case DCH_HH12:
- if (flag == TO_CHAR) {
- sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2,
- tm->tm_hour==0 ? 12 :
- tm->tm_hour <13 ? tm->tm_hour : tm->tm_hour-12);
- if (S_THth(suf))
- str_numth(p_inout, inout, 0);
- if (S_FM(suf) || S_THth(suf)) return strlen(p_inout)-1;
- else return 1;
- } else if (flag == FROM_CHAR) {
- if (S_FM(suf)) {
- sscanf(inout, "%d", &tm->tm_hour);
- return int4len((int4) tm->tm_hour)-1 + SKIP_THth(suf);
- } else {
- sscanf(inout, "%02d", &tm->tm_hour);
- return 1 + SKIP_THth(suf);
- }
-
- }
- case DCH_HH24:
- if (flag == TO_CHAR) {
- sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2, tm->tm_hour);
- if (S_THth(suf))
- str_numth(p_inout, inout, S_TH_TYPE(suf));
- if (S_FM(suf) || S_THth(suf)) return strlen(p_inout)-1;
- else return 1;
- } else if (flag == FROM_CHAR) {
- if (S_FM(suf)) {
- sscanf(inout, "%d", &tm->tm_hour);
- return int4len((int4) tm->tm_hour)-1 + SKIP_THth(suf);
- } else {
- sscanf(inout, "%02d", &tm->tm_hour);
- return 1 + SKIP_THth(suf);
- }
- }
- case DCH_MI:
- if (flag == TO_CHAR) {
- sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2, tm->tm_min);
- if (S_THth(suf))
- str_numth(p_inout, inout, S_TH_TYPE(suf));
- if (S_FM(suf) || S_THth(suf)) return strlen(p_inout)-1;
- else return 1;
- } else if (flag == FROM_CHAR) {
- if (S_FM(suf)) {
- sscanf(inout, "%d", &tm->tm_min);
- return int4len((int4) tm->tm_min)-1 + SKIP_THth(suf);
- } else {
- sscanf(inout, "%02d", &tm->tm_min);
- return 1 + SKIP_THth(suf);
- }
- }
- case DCH_SS:
- if (flag == TO_CHAR) {
- sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2, tm->tm_sec);
- if (S_THth(suf))
- str_numth(p_inout, inout, S_TH_TYPE(suf));
- if (S_FM(suf) || S_THth(suf)) return strlen(p_inout)-1;
- else return 1;
- } else if (flag == FROM_CHAR) {
- if (S_FM(suf)) {
- sscanf(inout, "%d", &tm->tm_sec);
- return int4len((int4) tm->tm_sec)-1 + SKIP_THth(suf);
- } else {
- sscanf(inout, "%02d", &tm->tm_sec);
- return 1 + SKIP_THth(suf);
- }
- }
- case DCH_SSSS:
- if (flag == TO_CHAR) {
- sprintf(inout, "%d", tm->tm_hour * 3600 +
- tm->tm_min * 60 +
- tm->tm_sec);
- if (S_THth(suf))
- str_numth(p_inout, inout, S_TH_TYPE(suf));
- return strlen(p_inout)-1;
- } else if (flag == FROM_CHAR)
- elog(ERROR, "%s: SSSS is not supported", FUNC_NAME);
- }
- return 0;
-}
-
-#define CHECK_SEQ_SEARCH(_l, _s) { \
- if (_l <= 0) { \
- elog(ERROR, "%s: bad value for %s", FUNC_NAME, _s); \
- } \
-}
-
-/*------
- * Master of DATE for TO_CHAR - write (inout) formated string
- * FROM_CHAR - scan (inout) string by course of FormatNode
- *------
- */
-#undef FUNC_NAME
-#define FUNC_NAME "dch_date"
-
-static int dch_date(int arg, char *inout, int suf, int flag, FormatNode *node)
-{
- char buff[MAX_NODE_SIZ],
- *p_inout;
- int i, len;
-
- p_inout = inout;
-
- /*------
- * In the FROM-char is not difference between "January" or "JANUARY"
- * or "january", all is before search convert to one-upper.
- * This convention is used for MONTH, MON, DAY, DY
- *------
- */
- if (flag == FROM_CHAR) {
- if (arg == DCH_MONTH || arg == DCH_Month || arg == DCH_month) {
-
- 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) {
-
- 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) {
-
- 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) {
-
- 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_MONTH:
- strcpy(inout, months_full[ tm->tm_mon - 1]);
- sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, str_toupper(inout));
- 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 ]);
- 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);
- if (S_FM(suf)) 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;
- case DCH_mon:
- strcpy(inout, months[ tm->tm_mon -1 ]);
- *inout = tolower(*inout);
- return 2;
- case DCH_MM:
- if (flag == TO_CHAR) {
- sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2, tm->tm_mon );
- if (S_THth(suf))
- str_numth(p_inout, inout, S_TH_TYPE(suf));
- if (S_FM(suf) || S_THth(suf))
- return strlen(p_inout)-1;
- else return 1;
- } else if (flag == FROM_CHAR) {
- if (S_FM(suf)) {
- sscanf(inout, "%d", &tm->tm_mon);
- return int4len((int4) tm->tm_mon)-1 + SKIP_THth(suf);
- } else {
- sscanf(inout, "%02d", &tm->tm_mon);
- return 1 + SKIP_THth(suf);
- }
- }
- case DCH_DAY:
- strcpy(inout, days[ tm->tm_wday ]);
- sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, str_toupper(inout));
- if (S_FM(suf)) return strlen(p_inout)-1;
- else return 8;
- case DCH_Day:
- sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, days[ tm->tm_wday]);
- if (S_FM(suf)) return strlen(p_inout)-1;
- else return 8;
- case DCH_day:
- sprintf(inout, "%*s", S_FM(suf) ? 0 : -9, days[ tm->tm_wday]);
- *inout = tolower(*inout);
- if (S_FM(suf)) return strlen(p_inout)-1;
- else return 8;
- case DCH_DY:
- strcpy(inout, days[ tm->tm_wday]);
- inout = str_toupper(inout);
- return 2;
- case DCH_Dy:
- strcpy(inout, days[ tm->tm_wday]);
- return 2;
- case DCH_dy:
- strcpy(inout, days[ tm->tm_wday]);
- *inout = tolower(*inout);
- return 2;
- case DCH_DDD:
- if (flag == TO_CHAR) {
- sprintf(inout, "%0*d", S_FM(suf) ? 0 : 3, tm->tm_yday);
- if (S_THth(suf))
- str_numth(p_inout, inout, S_TH_TYPE(suf));
- if (S_FM(suf) || S_THth(suf))
- return strlen(p_inout)-1;
- else return 2;
- } else if (flag == FROM_CHAR) {
- if (S_FM(suf)) {
- sscanf(inout, "%d", &tm->tm_yday);
- return int4len((int4) tm->tm_yday)-1 + SKIP_THth(suf);
- } else {
- sscanf(inout, "%03d", &tm->tm_yday);
- return 2 + SKIP_THth(suf);
- }
- }
- case DCH_DD:
- if (flag == TO_CHAR) {
- sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2, tm->tm_mday);
- if (S_THth(suf))
- str_numth(p_inout, inout, S_TH_TYPE(suf));
- if (S_FM(suf) || S_THth(suf))
- return strlen(p_inout)-1;
- else return 1;
- } else if (flag == FROM_CHAR) {
- if (S_FM(suf)) {
- sscanf(inout, "%d", &tm->tm_mday);
- return int4len((int4) tm->tm_mday)-1 + SKIP_THth(suf);
- } else {
- sscanf(inout, "%02d", &tm->tm_mday);
- return 1 + SKIP_THth(suf);
- }
- }
- case DCH_D:
- if (flag == TO_CHAR) {
- sprintf(inout, "%d", tm->tm_wday+1);
- if (S_THth(suf))
- str_numth(p_inout, inout, S_TH_TYPE(suf));
- if (S_THth(suf))
- return 2;
- return 0;
- } else if (flag == FROM_CHAR) {
- sscanf(inout, "%1d", &tm->tm_wday);
- if(tm->tm_wday) --tm->tm_wday;
- return 0 + SKIP_THth(suf);
- }
- case DCH_WW:
- if (flag == TO_CHAR) {
- sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2,
- (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))
- return strlen(p_inout)-1;
- else return 1;
- } else if (flag == FROM_CHAR)
- elog(ERROR, "%s: WW is not supported", FUNC_NAME);
- case DCH_Q:
- if (flag == TO_CHAR) {
- sprintf(inout, "%d", (tm->tm_mon-1)/3+1);
- if (S_THth(suf))
- str_numth(p_inout, inout, S_TH_TYPE(suf));
- if (S_THth(suf))
- return 2;
- return 0;
- } else if (flag == FROM_CHAR)
- elog(ERROR, "%s: Q is not supported", FUNC_NAME);
- case DCH_CC:
- if (flag == TO_CHAR) {
- i = tm->tm_year/100 +1;
- if (i <= 99 && i >= -99)
- sprintf(inout, "%0*d", S_FM(suf) ? 0 : 2, i);
- else
- sprintf(inout, "%d", i);
- if (S_THth(suf))
- str_numth(p_inout, inout, S_TH_TYPE(suf));
- return strlen(p_inout)-1;
- } else if (flag == FROM_CHAR)
- elog(ERROR, "%s: CC is not supported", FUNC_NAME);
- case DCH_Y_YYY:
- if (flag == TO_CHAR) {
- i= YEAR_ABS(tm->tm_year) / 1000;
- 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);
- return strlen(p_inout)-1;
- } else if (flag == FROM_CHAR) {
- int cc, yy;
- sscanf(inout, "%d,%03d", &cc, &yy);
- tm->tm_year = (cc * 1000) + yy;
-
- if (!S_FM(suf) && tm->tm_year <= 9999 && tm->tm_year >= -9999)
- len = 5;
- else
- 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;
- }
- case DCH_YYYY:
- if (flag == TO_CHAR) {
- if (tm->tm_year <= 9999 && tm->tm_year >= -9998)
- sprintf(inout, "%0*d", S_FM(suf) ? 0 : 4, YEAR_ABS(tm->tm_year));
- else
- 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);
- return strlen(p_inout)-1;
- } else if (flag == FROM_CHAR) {
- 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->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;
- }
- case DCH_YYY:
- if (flag == TO_CHAR) {
- sprintf(buff, "%03d", YEAR_ABS(tm->tm_year));
- i=strlen(buff);
- strcpy(inout, buff+(i-3));
- if (S_THth(suf))
- str_numth(p_inout, inout, S_TH_TYPE(suf));
- if (S_THth(suf)) return 4;
- return 2;
- } else if (flag == FROM_CHAR) {
- int yy;
- sscanf(inout, "%03d", &yy);
- tm->tm_year = (tm->tm_year/1000)*1000 +yy;
- return 2 + SKIP_THth(suf);
- }
- case DCH_YY:
- if (flag == TO_CHAR) {
- sprintf(buff, "%02d", YEAR_ABS(tm->tm_year));
- i=strlen(buff);
- strcpy(inout, buff+(i-2));
- if (S_THth(suf))
- str_numth(p_inout, inout, S_TH_TYPE(suf));
- if (S_THth(suf)) return 3;
- return 1;
- } else if (flag == FROM_CHAR) {
- int yy;
- sscanf(inout, "%02d", &yy);
- tm->tm_year = (tm->tm_year/100)*100 +yy;
- return 1 + SKIP_THth(suf);
- }
- case DCH_Y:
- if (flag == TO_CHAR) {
- sprintf(buff, "%1d", YEAR_ABS(tm->tm_year));
- i=strlen(buff);
- strcpy(inout, buff+(i-1));
- if (S_THth(suf))
- str_numth(p_inout, inout, S_TH_TYPE(suf));
- if (S_THth(suf)) return 2;
- return 0;
- } else if (flag == FROM_CHAR) {
- int yy;
- sscanf(inout, "%1d", &yy);
- tm->tm_year = (tm->tm_year/10)*10 +yy;
- return 0 + SKIP_THth(suf);
- }
- case DCH_RM:
- if (flag == TO_CHAR) {
- sprintf(inout, "%*s", S_FM(suf) ? 0 : -4,
- rm_months[ 12 - tm->tm_mon ]);
- if (S_FM(suf)) return strlen(p_inout)-1;
- else return 3;
- } else if (flag == FROM_CHAR) {
- tm->tm_mon = 11-seq_search(inout, rm_months, ALL_UPPER, FULL_SIZ, &len);
- CHECK_SEQ_SEARCH(len, "RM");
- ++tm->tm_mon;
- if (S_FM(suf)) return len-1;
- else return 3;
- }
- case DCH_W:
- if (flag == TO_CHAR) {
- sprintf(inout, "%d", (tm->tm_mday - tm->tm_wday +7) / 7 );
- if (S_THth(suf))
- str_numth(p_inout, inout, S_TH_TYPE(suf));
- if (S_THth(suf)) return 2;
- return 0;
- } else if (flag == FROM_CHAR)
- elog(ERROR, "%s: W is not supported", FUNC_NAME);
- case DCH_J:
- if (flag == TO_CHAR) {
- sprintf(inout, "%d", date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
- if (S_THth(suf))
- str_numth(p_inout, inout, S_TH_TYPE(suf));
- return strlen(p_inout)-1;
- } else if (flag == FROM_CHAR)
- elog(ERROR, "%s: J is not supported", FUNC_NAME);
- }
- return 0;
-}
-
-/****************************************************************************
- * Public routines
- ***************************************************************************/
-
-
-/*********************************************************************
- *
- * to_char
- *
- * Syntax:
- *
- * text *to_char(DateTime *dt, text *fmt)
- *
- * Purpose:
- *
- * Returns string, with date and/or time, formated at
- * argument 'fmt'
- *
- *********************************************************************/
-
-#undef FUNC_NAME
-#define FUNC_NAME "to_char"
-
-text
-*to_char(DateTime *dt, text *fmt)
-{
- FormatNode *tree;
- text *result;
- char *pars_str;
- double fsec;
- char *tzn;
- int len=0, tz;
-
- if ((!PointerIsValid(dt)) || (!PointerIsValid(fmt)))
- return NULL;
-
- len = VARSIZE(fmt) - VARHDRSZ;
-
- if (!len)
- return textin("");
-
- 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 (DATETIME_IS_EPOCH(*dt))
- {
- datetime2tm(SetDateTime(*dt), NULL, tm, &fsec, NULL);
- } else if (DATETIME_IS_CURRENT(*dt)) {
- datetime2tm(SetDateTime(*dt), &tz, tm, &fsec, &tzn);
- } else {
- if (datetime2tm(*dt, &tz, tm, &fsec, &tzn) != 0)
- elog(ERROR, "s%: Unable to convert datetime to tm", FUNC_NAME);
- }
-
- /* In dt.c is j2day as static :-(((
- tm->tm_wday = j2day(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday));
- must j2day convert itself...
- */
-
- tm->tm_wday = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) + 1) % 7;
- tm->tm_yday = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(tm->tm_year, 1,1) +1;
-
- tree = (FormatNode *) palloc(len * sizeof(FormatNode) +1);
- result = (text *) palloc( len * MAX_NODE_SIZ + VARHDRSZ);
- (tree + len)->type = NODE_LAST;
-
- pars_str = VARDATA(fmt);
- pars_str[ len ] = '\0';
-
- parse_format( tree, pars_str, keywords, suff, KWindex);
-
- node_action(tree, VARDATA(result), TO_CHAR);
- VARSIZE(result) = strlen(VARDATA(result)) + VARHDRSZ;
-
- return result;
-}
-
-
-/*********************************************************************
- *
- * from_char
- *
- * Syntax:
- *
- * DateTime *from_char(text *date_str, text *fmt)
- *
- * Purpose:
- *
- * Make DateTime from date_str which is formated at argument 'fmt'
- * ( from_char is reverse to_char() )
- *
- *********************************************************************/
-
-#undef FUNC_NAME
-#define FUNC_NAME "from_char"
-
-DateTime
-*from_char(text *date_str, text *fmt)
-{
- FormatNode *tree;
- DateTime *result;
- char *pars_str;
- int len=0,
- fsec=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(DateTime));
-
- len = VARSIZE(fmt) - VARHDRSZ;
-
- if (len) {
- tree = (FormatNode *) palloc((len+1) * sizeof(FormatNode));
- (tree + len)->type = NODE_LAST;
-
- pars_str = VARDATA(fmt);
- pars_str[ len ] = '\0';
- parse_format( tree, pars_str, keywords, suff, KWindex);
- VARDATA(date_str)[ VARSIZE(date_str) - VARHDRSZ ] = '\0';
- node_action(tree, VARDATA(date_str), FROM_CHAR);
- }
-
-#ifdef DEBUG_TO_FROM_CHAR
- NOTICE_TM;
-#endif
- if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday)) {
-
-#ifdef USE_POSIX_TIME
- tm->tm_isdst = -1;
- tm->tm_year -= 1900;
- tm->tm_mon -= 1;
-
-#ifdef DEBUG_TO_FROM_CHAR
- elog(NOTICE, "TO-FROM_CHAR: Call mktime()");
- NOTICE_TM;
-#endif
- mktime(tm);
- tm->tm_year += 1900;
- tm->tm_mon += 1;
-
-#if defined(HAVE_TM_ZONE)
- tz = -(tm->tm_gmtoff); /* tm_gmtoff is Sun/DEC-ism */
-#elif defined(HAVE_INT_TIMEZONE)
-
-#ifdef __CYGWIN__
- tz = (tm->tm_isdst ? (_timezone - 3600) : _timezone);
-#else
- tz = (tm->tm_isdst ? (timezone - 3600) : timezone);
-#endif
-
-#else
-#error USE_POSIX_TIME is defined but neither HAVE_TM_ZONE or HAVE_INT_TIMEZONE are defined
-#endif
-
-#else /* !USE_POSIX_TIME */
- tz = CTimeZone;
-#endif
- } else {
- tm->tm_isdst = 0;
- tz = 0;
- }
-#ifdef DEBUG_TO_FROM_CHAR
- NOTICE_TM;
-#endif
- if (tm2datetime(tm, fsec, &tz, result) != 0)
- elog(ERROR, "%s: can't convert 'tm' to datetime.", FUNC_NAME);
-
- return result;
-}
-
-/*********************************************************************
- *
- * to_date
- *
- * Syntax:
- *
- * DateADT *to_date(text *date_str, text *fmt)
- *
- * Purpose:
- *
- * Make Date from date_str which is formated at argument 'fmt'
- *
- *********************************************************************/
-
-#undef FUNC_NAME
-#define FUNC_NAME "to_date"
-
-DateADT
-to_date(text *date_str, text *fmt)
-{
- return datetime_date( from_char(date_str, fmt) );
-}
-
-
-/********************************************************************
- *
- * ordinal
- *
- * Syntax:
- *
- * text *ordinal(int4 num, text type)
- *
- * Purpose:
- *
- * Add to number 'th' suffix and return this as text.
- *
- ********************************************************************/
-
-#undef FUNC_NAME
-#define FUNC_NAME "ordinal"
-
-text
-*ordinal(int4 num, text *typ)
-{
- text *result;
- int ttt=0;
-
- if (!PointerIsValid(typ))
- return NULL;
-
- VARDATA(typ)[ VARSIZE(typ) - VARHDRSZ ] = '\0';
-
- if (!strcmp("TH", VARDATA(typ)))
- ttt = TH_UPPER;
- else if (!strcmp("th", VARDATA(typ)))
- ttt = TH_LOWER;
- else
- elog(ERROR, "%s: bad type '%s' (allowed: 'TH' or 'th')",
- FUNC_NAME, VARDATA(typ));
-
- result = (text *) palloc(16); /* ! not int8 ! */
-
- sprintf(VARDATA(result), "%d", (int) num);
- str_numth(VARDATA(result), VARDATA(result), ttt);
-
- VARSIZE(result) = strlen(VARDATA(result)) + VARHDRSZ;
-
- return result;
-}
diff --git a/contrib/dateformat/to-from_char.doc b/contrib/dateformat/to-from_char.doc
deleted file mode 100644
index 564de88189b..00000000000
--- a/contrib/dateformat/to-from_char.doc
+++ /dev/null
@@ -1,183 +0,0 @@
-
-
- TO_CHAR(datetime, text)
- -----------------------
- (returns text)
-
- TO_CHAR - the DateTime function for formating date and time outputs.
- This routine is inspire with the Oracle to_char().
-
- SELECT TO_CHAR('now'::datetime, 'HH:MI:SS YYYY');
- -------------
- 11:57:11 1999
-
-
- FROM_CHAR(text, text)
- ---------------------
- (returns DateTime)
-
- FROM_CHAR - the PostgreSQL extension routine which read non-datetime
- string and convert it to DateTime. This func. is inspire with the
- Oracle to_date() routine, but in Oracle this func. return date only
- and not support all keywords (format pictures).
-
- SELECT FROM_CHAR('11:57:11 1999', 'HH:MI:SS YYYY');
- ----------------------------
- Fri 01 Jan 11:57:11 1999 CET
-
-
- TO_DATE(text, text)
- -------------------
- (returns Date)
-
- TO_DATE - the Date function which read non-datetime (non-date) string
- and convert it to date. All for thos func. is just as from_char().
- This func. is inspire with the Oracle to_date() routine.
-
- SELECT TO_DATE('11:57:11 1999', 'HH:MI:SS YYYY');
- ----------
- 01-01-1999
-
-
-
- ----------------------------------
- String format-KeyWords and options:
- ----------------------------------
-
- * TO_CHAR (..., 'format picture')
- * FROM_CHAR (..., 'format picture')
- * TO_DATE (..., 'format picture')
-
- (Note: In Oracle manual is format-keyword called 'format pictures'.)
-
- All keywords has suffixes (prefix or postfix), example for 2 hours:
- keyword: HH (hour) 'HH' --> '02'
- prefix: FM (fill mode) 'FMHH' --> '2'
- postfix: TH (ordinal number) 'HHth' --> '02nd'
- 'FMHHth' --> '2nd'
-
- Suffixes:
- --------
- FM - fill mode
- 02 --> FMHH --> 2
- January , --> FMMonth --> January,
-
- TH - upper ordinal number
- 02 --> HHTH --> 02ND
-
- th - lower ordinal number
- 02 --> HHth --> 02th
-
-
- KeyWords (format pictures):
- --------------------------
-
- HH - hour of day (01-12)
- HH12 - -- // --
- HH24 - hour (00-24)
- MI - minute (00-59)
- SS - socond (00-59)
- SSSS - seconds past midnight (0-86399)
- Y,YYY - year with comma (full PgSQL datetime range) digits)
- YYYY - year (4 and more (full PgSQL datetime range) digits)
- YYY - last 3 digits of year
- YY - last 2 digits of year
- Y - last digit of year
- MONTH - full month name (upper) (9-letters)
- Month - full month name - first character is upper (9-letters)
- month - full month name - all characters is upper (9-letters)
- MON - abbreviated month name (3-letters)
- Mon - abbreviated month name (3-letters) - first character is upper
- mon - abbreviated month name (3-letters) - all characters is upper
- MM - month (01-12)
- DAY - full day name (upper) (9-letters)
- Day - full day name - first character is upper (9-letters)
- day - full day name - all characters is upper (9-letters)
- DY - abbreviated day name (3-letters) (upper)
- Dy - abbreviated day name (3-letters) - first character is upper
- Dy - abbreviated day name (3-letters) - all character is upper
- DDD - day of year (001-366)
- DD - day of month (01-31)
- D - day of week (1-7; SUN=1)
- WW - week number of year
- CC - century (2-digits)
- Q - quarter
- RM - roman numeral month (I=JAN; I-XII)
- W - week of month
- J - julian day (days since January 1, 4712 BC)
-
-
- AC / BC:
- -------
-
- TO-FROM CHAR routines support BC and AC postfix for years.
- You can combine BC and AC with TH.
-
- OTHER:
- -----
- '\' - must be use as double \\
-
- '\\HH\\MI\\SS' --> 11\45\56
-
- '"' - string berween a quotation marks is skipen and not
- is parsed. If you wand write '"' to output you must
- use \\"
-
- '"Month: "Month' --> Month: November
- '\\"YYYY Month\\"' --> "1999 November "
-
- text - the PostgreSQL TO-FROM CHAR support text without '"',
- but " text " is fastly and you have guarantee,
- that this text not will interprete as keyword.
-
- WARNING:
- -------
-
- You DON'T OMIT differention between fill mode (FM prefix)
- and standard input in FROM_CHAR (TO_DATE), because this
- routines can't scan your input string and conver it to
- Datetime. See:
-
- WRONG: FROM_CHAR('August 1999', 'Month YYYY');
-
- RIGHT: FROM_CHAR('August 1999', 'Month YYYY');
- or FROM_CHAR('August 1999', 'FMMonth YYYY');
-
- (! Month is 9-letters string if you not set fill-mode !)
-
-
----------------------------
-TODO / Now is not supported:
----------------------------
-
- - spelled-out SP suffix ( 22 --> Twenty-two )
- - AM/PM
-
- - not supported number to character converting
-
- TO_CHAR(number, 'format')
-
-
-
--------------------------------------------------------------------------------
-- secondary products :-) ------------------------------------------------------
--------------------------------------------------------------------------------
-
-
-ORDINAL(int4, text)
--------------------
-
- * Translate number to ordinal number and return this as text
-
-
-* Examples:
-
-template1=> select ordinal(21212, 'TH');
-ordinal
--------
-21212ND
-
-template1=> select ordinal(21212, 'th');
-ordinal
--------
-21212nd
diff --git a/contrib/dateformat/to-from_char.h b/contrib/dateformat/to-from_char.h
deleted file mode 100644
index e96e0a3797e..00000000000
--- a/contrib/dateformat/to-from_char.h
+++ /dev/null
@@ -1,18 +0,0 @@
-
-#ifndef TO_FROM_CHAR_H
-#define TO_FROM_CHAR_H
-
-/*------
- * For postgres
- *------
- */
-extern text *to_char(DateTime *dt, text *format);
-extern DateTime *from_char(text *date_str, text *format);
-extern DateADT to_date(text *date_str, text *format);
-
-extern text *ordinal(int4 num, text *type);
-
-extern char *months_full[]; /* full months name */
-extern char *rm_months[]; /* roman numeral of months */
-
-#endif \ No newline at end of file
diff --git a/contrib/dateformat/to-from_char.sql.in b/contrib/dateformat/to-from_char.sql.in
deleted file mode 100644
index 102a24ff465..00000000000
--- a/contrib/dateformat/to-from_char.sql.in
+++ /dev/null
@@ -1,29 +0,0 @@
--- to-from_char.sql datetime routines --
---
--- Copyright (c) 1999, Karel Zak "Zakkr" <zakkr@zf.jcu.cz>
---
--- This file is distributed under the GNU General Public License
--- either version 2, or (at your option) any later version.
-
-
--- Define the new functions
---
-
-create function to_char(datetime, text) returns text
- as 'MODULE_PATHNAME'
- language 'c';
-
-create function from_char(text, text) returns datetime
- as 'MODULE_PATHNAME'
- language 'c';
-
-create function to_date(text, text) returns date
- as 'MODULE_PATHNAME'
- language 'c';
-
-create function ordinal(int, text) returns text
- as 'MODULE_PATHNAME'
- language 'c';
-
-
--- end of file \ No newline at end of file