88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.54 2000/10/29 13:17:33 petere Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.55 2000/11/06 15:57:00 thomas Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -199,7 +199,11 @@ static datetkn datetktbl[] = {
199199 {"pst" , TZ , NEG (48 )}, /* Pacific Standard Time */
200200 {"sadt" , DTZ , 63 }, /* S. Australian Dayl. Time */
201201 {"sast" , TZ , 57 }, /* South Australian Std Time */
202+ #if USE_AUSTRALIAN_RULES
203+ {"sat" , TZ , 57 },
204+ #else
202205 {"sat" , DOW , 6 },
206+ #endif
203207 {"saturday" , DOW , 6 },
204208 {"sep" , MONTH , 9 },
205209 {"sept" , MONTH , 9 },
@@ -218,8 +222,7 @@ static datetkn datetktbl[] = {
218222 {"tue" , DOW , 2 },
219223 {"tues" , DOW , 2 },
220224 {"tuesday" , DOW , 2 },
221- {"undefined" , RESERV , DTK_INVALID }, /* "undefined" pre-v6.1 invalid
222- * time */
225+ {"undefined" , RESERV , DTK_INVALID }, /* pre-v6.1 invalid time */
223226 {"ut" , TZ , 0 },
224227 {"utc" , TZ , 0 },
225228 {"wadt" , DTZ , 48 }, /* West Australian DST */
@@ -235,10 +238,10 @@ static datetkn datetktbl[] = {
235238 {"ydt" , DTZ , NEG (48 )}, /* Yukon Daylight Time */
236239 {YESTERDAY , RESERV , DTK_YESTERDAY }, /* yesterday midnight */
237240 {"yst" , TZ , NEG (54 )}, /* Yukon Standard Time */
241+ {"z" , RESERV , DTK_ZULU }, /* 00:00:00 */
238242 {"zp4" , TZ , NEG (24 )}, /* GMT +4 hours. */
239243 {"zp5" , TZ , NEG (30 )}, /* GMT +5 hours. */
240244 {"zp6" , TZ , NEG (36 )}, /* GMT +6 hours. */
241- {"z" , RESERV , DTK_ZULU }, /* 00:00:00 */
242245 {ZULU , RESERV , DTK_ZULU }, /* 00:00:00 */
243246};
244247
@@ -466,25 +469,6 @@ ParseDateTime(char *timestr, char *lowstr,
466469 */
467470 if ((* cp == '-' ) || (* cp == '/' ) || (* cp == '.' ))
468471 {
469- #if 0
470-
471- /*
472- * special case of Posix timezone "GMT-0800" Note that
473- * other sign (e.g. "GMT+0800" is recognized as two
474- * separate fields and handled later. XXX There is no room
475- * for a delimiter between the "GMT" and the "-0800", so
476- * we are going to just swallow the "GMT". But this leads
477- * to other troubles with the definition of signs, so we
478- * have to flip - thomas 2000-02-06
479- */
480- if ((* cp == '-' ) && isdigit (* (cp + 1 ))
481- && (strncmp (field [nf ], "gmt" , 3 ) == 0 ))
482- {
483- * cp = '+' ;
484- continue ;
485- }
486- #endif
487-
488472 ftype [nf ] = DTK_DATE ;
489473 while (isdigit ((int ) * cp ) || (* cp == '-' ) || (* cp == '/' ) || (* cp == '.' ))
490474 * lp ++ = tolower (* cp ++ );
@@ -1667,8 +1651,7 @@ DecodeDateDelta(char **field, int *ftype, int nf, int *dtype, struct tm * tm, do
16671651 tmask ,
16681652 type ;
16691653 int i ;
1670- int flen ,
1671- val ;
1654+ int val ;
16721655 double fval ;
16731656 double sec ;
16741657
@@ -1695,14 +1678,40 @@ DecodeDateDelta(char **field, int *ftype, int nf, int *dtype, struct tm * tm, do
16951678 break ;
16961679
16971680 case DTK_TZ :
1698-
16991681 /*
17001682 * Timezone is a token with a leading sign character and
1701- * otherwise the same as a non-signed numeric field
1683+ * otherwise the same as a non-signed time field
17021684 */
1685+ Assert ((* field [i ] == '-' ) || (* field [i ] == '+' ));
1686+ /* A single signed number ends up here, but will be rejected by DecodeTime().
1687+ * So, work this out to drop through to DTK_NUMBER, which *can* tolerate this.
1688+ */
1689+ cp = field [i ]+ 1 ;
1690+ while ((* cp != '\0' ) && (* cp != ':' ))
1691+ cp ++ ;
1692+ if ((* cp == ':' )
1693+ && (DecodeTime ((field [i ]+ 1 ), fmask , & tmask , tm , fsec ) == 0 )) {
1694+ if (* field [i ] == '-' ) {
1695+ /* flip the sign on all fields */
1696+ tm -> tm_hour = - tm -> tm_hour ;
1697+ tm -> tm_min = - tm -> tm_min ;
1698+ tm -> tm_sec = - tm -> tm_sec ;
1699+ * fsec = - (* fsec );
1700+ }
1701+
1702+ /* Set the next type to be a day, if units are not specified.
1703+ * This handles the case of '1 +02:03' since we are reading right to left.
1704+ */
1705+ type = DTK_DAY ;
1706+ tmask = DTK_M (TZ );
1707+ break ;
1708+ }
1709+ /* DROP THROUGH */
1710+
17031711 case DTK_DATE :
17041712 case DTK_NUMBER :
17051713 val = strtol (field [i ], & cp , 10 );
1714+
17061715 if (* cp == '.' )
17071716 {
17081717 fval = strtod (cp , & cp );
@@ -1717,7 +1726,6 @@ DecodeDateDelta(char **field, int *ftype, int nf, int *dtype, struct tm * tm, do
17171726 else
17181727 return -1 ;
17191728
1720- flen = strlen (field [i ]);
17211729 tmask = 0 ; /* DTK_M(type); */
17221730
17231731 switch (type )
@@ -2193,98 +2201,126 @@ EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str)
21932201 int is_nonzero = FALSE;
21942202 char * cp = str ;
21952203
2204+ /* The sign of year and month are guaranteed to match,
2205+ * since they are stored internally as "month".
2206+ * But we'll need to check for is_before and is_nonzero
2207+ * when determining the signs of hour/minute/seconds fields.
2208+ */
21962209 switch (style )
21972210 {
21982211 /* compatible with ISO date formats */
21992212 case USE_ISO_DATES :
2200- break ;
2201-
2202- default :
2203- strcpy (cp , "@ " );
2204- cp += strlen (cp );
2205- break ;
2206- }
2207-
2208- if (tm -> tm_year != 0 )
2209- {
2210- is_before |= (tm -> tm_year < 0 );
2211- sprintf (cp , "%d year%s" ,
2212- abs (tm -> tm_year ), ((abs (tm -> tm_year ) != 1 ) ? "s" : "" ));
2213- cp += strlen (cp );
2214- is_nonzero = TRUE;
2215- }
2216-
2217- if (tm -> tm_mon != 0 )
2218- {
2219- is_before |= (tm -> tm_mon < 0 );
2220- sprintf (cp , "%s%d mon%s" , (is_nonzero ? " " : "" ),
2221- abs (tm -> tm_mon ), ((abs (tm -> tm_mon ) != 1 ) ? "s" : "" ));
2222- cp += strlen (cp );
2223- is_nonzero = TRUE;
2224- }
2225-
2226- switch (style )
2227- {
2228- /* compatible with ISO date formats */
2229- case USE_ISO_DATES :
2230- if (tm -> tm_mday != 0 )
2213+ if (tm -> tm_year != 0 )
22312214 {
2232- is_before |= ( tm -> tm_mday < 0 );
2233- sprintf ( cp , "%s%d" , ( is_nonzero ? " " : "" ), abs ( tm -> tm_mday ));
2215+ sprintf ( cp , "%d year%s" ,
2216+ tm -> tm_year , (( tm -> tm_year != 1 ) ? "s " : "" ));
22342217 cp += strlen (cp );
22352218 is_nonzero = TRUE;
22362219 }
2237- is_before |= ((tm -> tm_hour < 0 ) || (tm -> tm_min < 0 ));
2238- sprintf (cp , "%s%02d:%02d" , (is_nonzero ? " " : "" ),
2239- abs (tm -> tm_hour ), abs (tm -> tm_min ));
2240- cp += strlen (cp );
2241- /* Mark as "non-zero" since the fields are now filled in */
2242- is_nonzero = TRUE;
22432220
2244- /* fractional seconds? */
2245- if (fsec != 0 )
2221+ if (tm -> tm_mon != 0 )
22462222 {
2247- fsec += tm -> tm_sec ;
2248- is_before |= (fsec < 0 );
2249- sprintf (cp , ":%05.2f" , fabs (fsec ));
2223+ sprintf (cp , "%s%d mon%s" , (is_nonzero ? " " : "" ),
2224+ tm -> tm_mon , ((tm -> tm_mon != 1 ) ? "s" : "" ));
22502225 cp += strlen (cp );
22512226 is_nonzero = TRUE;
2227+ }
22522228
2253- /* otherwise, integer seconds only? */
2229+ if (tm -> tm_mday != 0 )
2230+ {
2231+ sprintf (cp , "%s%d" , (is_nonzero ? " " : "" ), tm -> tm_mday );
2232+ cp += strlen (cp );
2233+ is_nonzero = TRUE;
22542234 }
2255- else if (tm -> tm_sec != 0 )
22562235 {
2257- is_before |= (tm -> tm_sec < 0 );
2258- sprintf (cp , ":%02d" , abs (tm -> tm_sec ));
2236+ int minus = ((tm -> tm_hour < 0 ) || (tm -> tm_min < 0 )
2237+ || (tm -> tm_sec < 0 ) || (fsec < 0 ));
2238+
2239+ sprintf (cp , "%s%s%02d:%02d" , (is_nonzero ? " " : "" ),
2240+ (minus ? "-" : "+" ),
2241+ abs (tm -> tm_hour ), abs (tm -> tm_min ));
22592242 cp += strlen (cp );
2243+ /* Mark as "non-zero" since the fields are now filled in */
22602244 is_nonzero = TRUE;
2245+
2246+ /* fractional seconds? */
2247+ if (fsec != 0 )
2248+ {
2249+ fsec += tm -> tm_sec ;
2250+ sprintf (cp , ":%05.2f" , fabs (fsec ));
2251+ cp += strlen (cp );
2252+ is_nonzero = TRUE;
2253+
2254+ /* otherwise, integer seconds only? */
2255+ }
2256+ else if (tm -> tm_sec != 0 )
2257+ {
2258+ sprintf (cp , ":%02d" , abs (tm -> tm_sec ));
2259+ cp += strlen (cp );
2260+ is_nonzero = TRUE;
2261+ }
22612262 }
22622263 break ;
22632264
22642265 case USE_POSTGRES_DATES :
22652266 default :
2267+ strcpy (cp , "@ " );
2268+ cp += strlen (cp );
2269+
2270+ if (tm -> tm_year != 0 )
2271+ {
2272+ is_before = (tm -> tm_year < 0 );
2273+ if (is_before )
2274+ tm -> tm_year = - tm -> tm_year ;
2275+ sprintf (cp , "%d year%s" ,
2276+ tm -> tm_year , ((tm -> tm_year != 1 ) ? "s" : "" ));
2277+ cp += strlen (cp );
2278+ is_nonzero = TRUE;
2279+ }
2280+
2281+ if (tm -> tm_mon != 0 )
2282+ {
2283+ if (! is_nonzero )
2284+ is_before = (tm -> tm_mon < 0 );
2285+ if (is_before )
2286+ tm -> tm_mon = - tm -> tm_mon ;
2287+ sprintf (cp , "%s%d mon%s" , (is_nonzero ? " " : "" ),
2288+ tm -> tm_mon , ((tm -> tm_mon != 1 ) ? "s" : "" ));
2289+ cp += strlen (cp );
2290+ is_nonzero = TRUE;
2291+ }
2292+
22662293 if (tm -> tm_mday != 0 )
22672294 {
2268- is_before |= (tm -> tm_mday < 0 );
2295+ if (! is_nonzero )
2296+ is_before = (tm -> tm_mday < 0 );
2297+ if (is_before )
2298+ tm -> tm_mday = - tm -> tm_mday ;
22692299 sprintf (cp , "%s%d day%s" , (is_nonzero ? " " : "" ),
2270- abs ( tm -> tm_mday ) , ((abs ( tm -> tm_mday ) != 1 ) ? "s" : "" ));
2300+ tm -> tm_mday , ((tm -> tm_mday != 1 ) ? "s" : "" ));
22712301 cp += strlen (cp );
22722302 is_nonzero = TRUE;
22732303 }
22742304 if (tm -> tm_hour != 0 )
22752305 {
2276- is_before |= (tm -> tm_hour < 0 );
2306+ if (! is_nonzero )
2307+ is_before = (tm -> tm_hour < 0 );
2308+ if (is_before )
2309+ tm -> tm_hour = - tm -> tm_hour ;
22772310 sprintf (cp , "%s%d hour%s" , (is_nonzero ? " " : "" ),
2278- abs ( tm -> tm_hour ) , ((abs ( tm -> tm_hour ) != 1 ) ? "s" : "" ));
2311+ tm -> tm_hour , ((tm -> tm_hour != 1 ) ? "s" : "" ));
22792312 cp += strlen (cp );
22802313 is_nonzero = TRUE;
22812314 }
22822315
22832316 if (tm -> tm_min != 0 )
22842317 {
2285- is_before |= (tm -> tm_min < 0 );
2318+ if (! is_nonzero )
2319+ is_before = (tm -> tm_min < 0 );
2320+ if (is_before )
2321+ tm -> tm_min = - tm -> tm_min ;
22862322 sprintf (cp , "%s%d min%s" , (is_nonzero ? " " : "" ),
2287- abs ( tm -> tm_min ) , ((abs ( tm -> tm_min ) != 1 ) ? "s" : "" ));
2323+ tm -> tm_min , ((tm -> tm_min != 1 ) ? "s" : "" ));
22882324 cp += strlen (cp );
22892325 is_nonzero = TRUE;
22902326 }
@@ -2293,26 +2329,32 @@ EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str)
22932329 if (fsec != 0 )
22942330 {
22952331 fsec += tm -> tm_sec ;
2296- is_before |= (fsec < 0 );
2297- sprintf (cp , "%s%.2f secs" , (is_nonzero ? " " : "" ), fabs (fsec ));
2332+ if (! is_nonzero )
2333+ is_before = (fsec < 0 );
2334+ if (is_before )
2335+ fsec = - fsec ;
2336+ sprintf (cp , "%s%.2f secs" , (is_nonzero ? " " : "" ), fsec );
22982337 cp += strlen (cp );
22992338 is_nonzero = TRUE;
23002339
23012340 /* otherwise, integer seconds only? */
23022341 }
23032342 else if (tm -> tm_sec != 0 )
23042343 {
2305- is_before |= (tm -> tm_sec < 0 );
2344+ if (! is_nonzero )
2345+ is_before = (tm -> tm_sec < 0 );
2346+ if (is_before )
2347+ tm -> tm_sec = - tm -> tm_sec ;
23062348 sprintf (cp , "%s%d sec%s" , (is_nonzero ? " " : "" ),
2307- abs ( tm -> tm_sec ) , ((abs ( tm -> tm_sec ) != 1 ) ? "s" : "" ));
2349+ tm -> tm_sec , ((tm -> tm_sec != 1 ) ? "s" : "" ));
23082350 cp += strlen (cp );
23092351 is_nonzero = TRUE;
23102352 }
23112353 break ;
23122354 }
23132355
23142356 /* identically zero? then put in a unitless zero... */
2315- if (!is_nonzero )
2357+ if (! is_nonzero )
23162358 {
23172359 strcat (cp , "0" );
23182360 cp += strlen (cp );
0 commit comments