Thread: New datestyle(s)

New datestyle(s)

From
Peter Koczan
Date:
Anyway, this is in response to a really old request of mine to easily
and automatically get a datestyle for a different DBMS as part of an
ongoing port process
(http://archives.postgresql.org/pgsql-sql/2008-05/msg00048.php).

I patched this a while ago and I finally got a chance to test it.
Overall, it was pretty easy once I figured out how existing datestyles
were coded (lots of grep'ing was involved). So, I figured I'd share
what I did and also share the source patch in case anyone would either
like a Sybase/SQL Server datestyle or a model on how to add your own
custom datestyles.

You need to edit the following files:
src/backend/commands/variable.c - Add in your new datestyle to the
list to allow it to be a valid option for "SET datestyle TO <x>"
src/backend/utils/adt/datetime.c - Define your output format. A little
hack-ish but pretty straightforward overall.
src/include/miscadmin.h - Define your new datestyle.
src/bin/psql/tab-complete.c - Not necessary to add it, but having it
in the list of tab completions for datestyle is nice.

I don't use the ecpg interface, so I didn't bother patching that. It
seems like it would be analogous to what's been done already.

Peter

Index: src/backend/commands/variable.c
===================================================================
RCS file: /s/postgresql-8.3.3/src/CVSROOT/postgresql-8.3.3/src/backend/commands/variable.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- src/backend/commands/variable.c    3 Sep 2008 18:30:21 -0000    1.1
+++ src/backend/commands/variable.c    3 Sep 2008 18:52:50 -0000    1.2
@@ -100,6 +100,13 @@            if (!have_order)                newDateOrder = DATEORDER_DMY;        }
+        else if (pg_strcasecmp(tok, "SYBASE") == 0)
+        {
+            if (have_style && newDateStyle != USE_SYBASE_DATES)
+                ok = false;        /* conflicting styles */
+            newDateStyle = USE_SYBASE_DATES;
+            have_style = true;
+        }        else if (pg_strcasecmp(tok, "YMD") == 0)        {            if (have_order && newDateOrder !=
DATEORDER_YMD)
@@ -200,6 +207,9 @@        case USE_GERMAN_DATES:            strcpy(result, "German");            break;
+        case USE_SYBASE_DATES:
+            strcpy(result, "Sybase");
+            break;        default:            strcpy(result, "Postgres");            break;
Index: src/backend/utils/adt/datetime.c
===================================================================
RCS file: /s/postgresql-8.3.3/src/CVSROOT/postgresql-8.3.3/src/backend/utils/adt/datetime.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- src/backend/utils/adt/datetime.c    3 Sep 2008 18:30:26 -0000    1.1
+++ src/backend/utils/adt/datetime.c    3 Sep 2008 18:53:29 -0000    1.2
@@ -3233,6 +3233,15 @@                sprintf(str + 5, ".%04d %s", -(tm->tm_year - 1), "BC");            break;

+        case USE_SYBASE_DATES:
+            /* Sybase date format */
+            sprintf(str, "%s %2d", months[tm->tm_mon - 1], tm->tm_mday);
+            if (tm->tm_year > 0)
+                sprintf(str + 6, " %04d", tm->tm_year);
+            else
+                sprintf(str + 6, " %04d %s", -(tm->tm_year - 1), "BC");
+            break;
+        case USE_POSTGRES_DATES:        default:            /* traditional date-only style for Postgres */
@@ -3302,6 +3311,8 @@EncodeDateTime(struct pg_tm * tm, fsec_t fsec, int *tzp, char **tzn,
int style, char *str){    int            day;
+    bool            meridian;
+    int            temp_hour;
    /*     * Why are we checking only the month field? Change this to an assert...
@@ -3452,6 +3463,32 @@                sprintf(str + strlen(str), " BC");            break;

+        case USE_SYBASE_DATES:
+            /* Sybase date format */
+            meridian = true; // true = AM, false = PM
+            temp_hour = tm->tm_hour;
+
+            if (temp_hour < 12)
+            {
+                meridian = true;
+                if (temp_hour == 0) temp_hour = 12;
+            }
+            else
+            {
+                meridian = false;
+                if (temp_hour > 12) temp_hour -= 12;
+            }
+
+            sprintf(str, "%s %2d %04d %2d:%02d%s",
+                        months[tm->tm_mon - 1], tm->tm_mday,
+                        (tm->tm_year > 0) ? tm->tm_year : -(tm->tm_year - 1),
+                        temp_hour, tm->tm_min,
+                        (meridian) ? "AM" : "PM");
+
+            if (tm->tm_year <= 0)
+                sprintf(str + strlen(str), " BC");
+            break;
+        case USE_POSTGRES_DATES:        default:            /* Backward-compatible with traditional Postgres abstime
dates*/
 
Index: src/include/miscadmin.h
===================================================================
RCS file: /s/postgresql-8.3.3/src/CVSROOT/postgresql-8.3.3/src/include/miscadmin.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- src/include/miscadmin.h    3 Sep 2008 18:30:34 -0000    1.1
+++ src/include/miscadmin.h    3 Sep 2008 18:53:45 -0000    1.2
@@ -183,6 +183,7 @@#define USE_SQL_DATES            2#define USE_GERMAN_DATES        3#define USE_XSD_DATES
4
+#define USE_SYBASE_DATES        5
/* valid DateOrder values */#define DATEORDER_YMD            0
Index: src/bin/psql/tab-complete.c
===================================================================
RCS file: /s/postgresql-8.3.3/src/CVSROOT/postgresql-8.3.3/src/bin/psql/tab-complete.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- src/bin/psql/tab-complete.c    3 Sep 2008 18:30:34 -0000    1.1
+++ src/bin/psql/tab-complete.c    3 Sep 2008 18:53:42 -0000    1.2
@@ -1888,7 +1888,7 @@        if (pg_strcasecmp(prev2_wd, "DateStyle") == 0)        {            static const char
*constmy_list[] =
 
-            {"ISO", "SQL", "Postgres", "German",
+            {"ISO", "SQL", "Postgres", "German", "Sybase",                "YMD", "DMY", "MDY",                "US",
"European","NonEuropean",            "DEFAULT", NULL};