OSDN Git Service

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 99c7d0f..d4fb075 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,