8
8
*
9
9
*
10
10
* 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 $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -199,7 +199,11 @@ static datetkn datetktbl[] = {
199
199
{"pst" , TZ , NEG (48 )}, /* Pacific Standard Time */
200
200
{"sadt" , DTZ , 63 }, /* S. Australian Dayl. Time */
201
201
{"sast" , TZ , 57 }, /* South Australian Std Time */
202
+ #if USE_AUSTRALIAN_RULES
203
+ {"sat" , TZ , 57 },
204
+ #else
202
205
{"sat" , DOW , 6 },
206
+ #endif
203
207
{"saturday" , DOW , 6 },
204
208
{"sep" , MONTH , 9 },
205
209
{"sept" , MONTH , 9 },
@@ -218,8 +222,7 @@ static datetkn datetktbl[] = {
218
222
{"tue" , DOW , 2 },
219
223
{"tues" , DOW , 2 },
220
224
{"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 */
223
226
{"ut" , TZ , 0 },
224
227
{"utc" , TZ , 0 },
225
228
{"wadt" , DTZ , 48 }, /* West Australian DST */
@@ -235,10 +238,10 @@ static datetkn datetktbl[] = {
235
238
{"ydt" , DTZ , NEG (48 )}, /* Yukon Daylight Time */
236
239
{YESTERDAY , RESERV , DTK_YESTERDAY }, /* yesterday midnight */
237
240
{"yst" , TZ , NEG (54 )}, /* Yukon Standard Time */
241
+ {"z" , RESERV , DTK_ZULU }, /* 00:00:00 */
238
242
{"zp4" , TZ , NEG (24 )}, /* GMT +4 hours. */
239
243
{"zp5" , TZ , NEG (30 )}, /* GMT +5 hours. */
240
244
{"zp6" , TZ , NEG (36 )}, /* GMT +6 hours. */
241
- {"z" , RESERV , DTK_ZULU }, /* 00:00:00 */
242
245
{ZULU , RESERV , DTK_ZULU }, /* 00:00:00 */
243
246
};
244
247
@@ -466,25 +469,6 @@ ParseDateTime(char *timestr, char *lowstr,
466
469
*/
467
470
if ((* cp == '-' ) || (* cp == '/' ) || (* cp == '.' ))
468
471
{
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
-
488
472
ftype [nf ] = DTK_DATE ;
489
473
while (isdigit ((int ) * cp ) || (* cp == '-' ) || (* cp == '/' ) || (* cp == '.' ))
490
474
* lp ++ = tolower (* cp ++ );
@@ -1667,8 +1651,7 @@ DecodeDateDelta(char **field, int *ftype, int nf, int *dtype, struct tm * tm, do
1667
1651
tmask ,
1668
1652
type ;
1669
1653
int i ;
1670
- int flen ,
1671
- val ;
1654
+ int val ;
1672
1655
double fval ;
1673
1656
double sec ;
1674
1657
@@ -1695,14 +1678,40 @@ DecodeDateDelta(char **field, int *ftype, int nf, int *dtype, struct tm * tm, do
1695
1678
break ;
1696
1679
1697
1680
case DTK_TZ :
1698
-
1699
1681
/*
1700
1682
* 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
1702
1684
*/
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
+
1703
1711
case DTK_DATE :
1704
1712
case DTK_NUMBER :
1705
1713
val = strtol (field [i ], & cp , 10 );
1714
+
1706
1715
if (* cp == '.' )
1707
1716
{
1708
1717
fval = strtod (cp , & cp );
@@ -1717,7 +1726,6 @@ DecodeDateDelta(char **field, int *ftype, int nf, int *dtype, struct tm * tm, do
1717
1726
else
1718
1727
return -1 ;
1719
1728
1720
- flen = strlen (field [i ]);
1721
1729
tmask = 0 ; /* DTK_M(type); */
1722
1730
1723
1731
switch (type )
@@ -2193,98 +2201,126 @@ EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str)
2193
2201
int is_nonzero = FALSE;
2194
2202
char * cp = str ;
2195
2203
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
+ */
2196
2209
switch (style )
2197
2210
{
2198
2211
/* compatible with ISO date formats */
2199
2212
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 )
2231
2214
{
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 " : "" ));
2234
2217
cp += strlen (cp );
2235
2218
is_nonzero = TRUE;
2236
2219
}
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;
2243
2220
2244
- /* fractional seconds? */
2245
- if (fsec != 0 )
2221
+ if (tm -> tm_mon != 0 )
2246
2222
{
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" : "" ));
2250
2225
cp += strlen (cp );
2251
2226
is_nonzero = TRUE;
2227
+ }
2252
2228
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;
2254
2234
}
2255
- else if (tm -> tm_sec != 0 )
2256
2235
{
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 ));
2259
2242
cp += strlen (cp );
2243
+ /* Mark as "non-zero" since the fields are now filled in */
2260
2244
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
+ }
2261
2262
}
2262
2263
break ;
2263
2264
2264
2265
case USE_POSTGRES_DATES :
2265
2266
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
+
2266
2293
if (tm -> tm_mday != 0 )
2267
2294
{
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 ;
2269
2299
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" : "" ));
2271
2301
cp += strlen (cp );
2272
2302
is_nonzero = TRUE;
2273
2303
}
2274
2304
if (tm -> tm_hour != 0 )
2275
2305
{
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 ;
2277
2310
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" : "" ));
2279
2312
cp += strlen (cp );
2280
2313
is_nonzero = TRUE;
2281
2314
}
2282
2315
2283
2316
if (tm -> tm_min != 0 )
2284
2317
{
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 ;
2286
2322
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" : "" ));
2288
2324
cp += strlen (cp );
2289
2325
is_nonzero = TRUE;
2290
2326
}
@@ -2293,26 +2329,32 @@ EncodeTimeSpan(struct tm * tm, double fsec, int style, char *str)
2293
2329
if (fsec != 0 )
2294
2330
{
2295
2331
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 );
2298
2337
cp += strlen (cp );
2299
2338
is_nonzero = TRUE;
2300
2339
2301
2340
/* otherwise, integer seconds only? */
2302
2341
}
2303
2342
else if (tm -> tm_sec != 0 )
2304
2343
{
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 ;
2306
2348
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" : "" ));
2308
2350
cp += strlen (cp );
2309
2351
is_nonzero = TRUE;
2310
2352
}
2311
2353
break ;
2312
2354
}
2313
2355
2314
2356
/* identically zero? then put in a unitless zero... */
2315
- if (!is_nonzero )
2357
+ if (! is_nonzero )
2316
2358
{
2317
2359
strcat (cp , "0" );
2318
2360
cp += strlen (cp );
0 commit comments