]> granicus.if.org Git - postgresql/commitdiff
From: "D'Arcy J.M. Cain" <darcy@druid.net>
authorMarc G. Fournier <scrappy@hub.org>
Thu, 3 Apr 1997 19:58:11 +0000 (19:58 +0000)
committerMarc G. Fournier <scrappy@hub.org>
Thu, 3 Apr 1997 19:58:11 +0000 (19:58 +0000)
Subject: [HACKERS] timestamp.c changes

I sent in changes previously and they were rejected because they didn't
follow ANSI spec.  Here is the input part of the changes again.  Even
though it allows more flexibility for inputting different formats, it
is also backwards compatible with the standard version.  I have also
not changed the output format so it will still output the ANSI forms.
Is this acceptable to everyone?

src/backend/utils/adt/timestamp.c

index 99c7d0f70f09138b9319eab4c2e2e8bb927606a1..d4fb0759644150f814b57ea814a7e763e3159af1 100644 (file)
 #include <stdio.h>
 #include <string.h>
 #include <time.h>
+#include <ctype.h>
 #include "postgres.h"
 #include "utils/builtins.h"
 
+/* copy the next part of the string into a buffer */
+static const char *
+cpstr(const char *s, char *buf)
+{
+       char in = 0;
+
+       while (isspace(*s))
+               s++;
+
+       for (; *s && !isspace(*s); s++)
+       {
+               if (strchr("-,:/", *s))
+               {
+                       buf[in] = 0;
+                       return(s + 1);
+               }
+
+               if (in < 16)
+                       buf[in++] = tolower(*s);
+       }
+
+       buf[in] = 0;
+       return s;
+}
+
+/* assumes dd/mm/yyyy unless first item is month in word form */
 time_t
 timestamp_in(const char *timestamp_str)
 {
     struct tm input_time;
     int4 result;
+       char buf[18];
+       const char *p;
+       static const char *mstr[] = {
+               "january", "february", "march", "april", "may", "june",
+               "july", "august", "september", "october", "november", "december"
+       };
 
     memset(&input_time, 0, sizeof(input_time));
-    if(sscanf(timestamp_str, "%d%*c%d%*c%d%*c%d%*c%d%*c%d",
-             &input_time.tm_year, &input_time.tm_mon, &input_time.tm_mday,
-             &input_time.tm_hour, &input_time.tm_min, &input_time.tm_sec) != 6) {
-       elog(WARN, "timestamp_in: timestamp \"%s\" not of the form yyyy-mm-dd hh:mm:ss",
+       p = cpstr(timestamp_str, buf);
+       if (isdigit(buf[0]))    /* must be dd/mm/yyyy */
+       {
+               input_time.tm_mday = atoi(buf);
+               p = cpstr(p, buf);
+               if (!buf[0])
+                       elog(WARN, "timestamp_in: timestamp \"%s\" not a proper date",
+                                       timestamp_str);
+               if (isdigit(buf[0]))
+               {
+                       input_time.tm_mon = atoi(buf) - 1;
+                       if (input_time.tm_mon < 0 || input_time.tm_mon > 11)
+                               elog(WARN, "timestamp_in: timestamp \"%s\" invalid month",
+                                       timestamp_str);
+               }
+               else
+               {
+                       int i;
+                       for (i = 0; i < 12; i++)
+                               if (strncmp(mstr[i], buf, strlen(buf)) == 0)
+                                       break;
+                       if (1 > 11)
+                               elog(WARN, "timestamp_in: timestamp \"%s\" invalid month",
+                                               timestamp_str);
+                       input_time.tm_mon = i;
+               }
+       }
+       else    /* must be month/dd/yyyy */
+       {
+               int i;
+               for (i = 0; i < 12; i++)
+                       if (strncmp(mstr[i], buf, strlen(buf)) == 0)
+                               break;
+               if (1 > 11)
+                       elog(WARN, "timestamp_in: timestamp \"%s\" invalid month",
+                                       timestamp_str);
+               input_time.tm_mon = i;
+               p = cpstr(p, buf);
+               input_time.tm_mday = atoi(buf);
+               if (!input_time.tm_mday || input_time.tm_mday > 31)
+                       elog(WARN, "timestamp_in: timestamp \"%s\" not a proper date",
             timestamp_str);
     }
 
-    /* range checking?  bahahahaha.... */
-
-    input_time.tm_year -= 1900;
-    input_time.tm_mon -= 1;
+       p = cpstr(p, buf);
+       if (!buf[0] || !isdigit(buf[0]))
+               elog(WARN, "timestamp_in: timestamp \"%s\" not a proper date",
+                               timestamp_str);
+       if ((input_time.tm_year = atoi(buf)) < 1900)
+               input_time.tm_year += 1900;
+
+       /* now get the time */
+       p = cpstr(p, buf);
+       input_time.tm_hour = atoi(buf);
+       p = cpstr(p, buf);
+       input_time.tm_min = atoi(buf);
+       p = cpstr(p, buf);
+       input_time.tm_sec = atoi(buf);
 
     /* use mktime(), but make this GMT, not local time */
     result = mktime(&input_time);
@@ -35,7 +115,7 @@ timestamp_out(time_t timestamp)
     char *result;
     struct tm *time;
 
-    time = localtime((time_t *)&timestamp);
+    time = localtime(&timestamp);
     result = palloc(20);
     sprintf(result, "%04d-%02d-%02d %02d:%02d:%02d",
            time->tm_year+1900, time->tm_mon+1, time->tm_mday,