diff options
| author | Bruce Momjian | 2000-01-25 23:53:56 +0000 |
|---|---|---|
| committer | Bruce Momjian | 2000-01-25 23:53:56 +0000 |
| commit | b866d2e2d79416f8497e4dffa7e800298d018f6c (patch) | |
| tree | b633b1415e4b916aaff71d86dc8cee4dba0258e9 /contrib | |
| parent | 90aaad06cf25753e10717ac7eb727cd65d8d5726 (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/README | 4 | ||||
| -rw-r--r-- | contrib/dateformat/Makefile | 71 | ||||
| -rw-r--r-- | contrib/dateformat/test/Makefile | 25 | ||||
| -rw-r--r-- | contrib/dateformat/test/README | 33 | ||||
| -rw-r--r-- | contrib/dateformat/test/rand_datetime.c | 71 | ||||
| -rw-r--r-- | contrib/dateformat/test/regress.sql | 58 | ||||
| -rw-r--r-- | contrib/dateformat/to-from_char.c | 1382 | ||||
| -rw-r--r-- | contrib/dateformat/to-from_char.doc | 183 | ||||
| -rw-r--r-- | contrib/dateformat/to-from_char.h | 18 | ||||
| -rw-r--r-- | contrib/dateformat/to-from_char.sql.in | 29 |
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 |
