mirror of https://github.com/postgres/postgres
TO_DATE()
and PgSQL extension FROM_CHAR().
TO_CHAR() routine allow formating text output with a datetime values:
SELECT TO_CHAR('now'::datetime, '"Now is: "HH24:MI:SS');
to_char
----------------
Now is: 21:04:10
FROM_CHAR() routine allow convert text to a datetime:
SELECT FROM_CHAR('September 1999 10:20:30', 'FMMonth YYYY
HH:MI:SS');
from_char
-----------------------------
Wed Sep 01 10:20:30 1999 CEST
TO_DATE() is equal with FROM_CHAR(), but output a Date only:
SELECT TO_DATE('September 1999 10:20:30', 'FMMonth YYYY
HH:MI:SS');
to_date
----------
09-01-1999
In attache is compressed dir for the contrib. All is prepared, but I'am
not
sure if Makefile is good (probably yes).
Comments & suggestions ?
Thomas, thank you for your good advices.
Karel
------------------------------------------------------------------------------
Karel Zak <zakkr@zf.jcu.cz>
http://home.zf.jcu.cz/~zakkr/
REL7_0_PATCHES
parent
1f747c6722
commit
1c5aec60bb
@ -0,0 +1,71 @@ |
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# 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 |
||||
@ -0,0 +1,25 @@ |
||||
|
||||
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)
|
||||
@ -0,0 +1,33 @@ |
||||
|
||||
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 (?). |
||||
|
||||
|
||||
|
||||
@ -0,0 +1,71 @@ |
||||
|
||||
#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); |
||||
} |
||||
@ -0,0 +1,58 @@ |
||||
|
||||
--- |
||||
--- 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"; |
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,183 @@ |
||||
|
||||
|
||||
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 |
||||
@ -0,0 +1,18 @@ |
||||
|
||||
#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 |
||||
@ -0,0 +1,29 @@ |
||||
-- 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 |
||||
Loading…
Reference in new issue