88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.153 2005/09 /0906:46:14 tgl Exp $
11+ * $PostgreSQL: pgsql/src/backend/utils/adt/timestamp.c,v 1.154 2005/10 /0917:21:46 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -998,10 +998,8 @@ dt2time(Timestamp jd, int *hour, int *min, int *sec, fsec_t *fsec)
998998* min = time /SECS_PER_MINUTE ;
999999time -= (* min )* SECS_PER_MINUTE ;
10001000* sec = time ;
1001- * fsec = JROUND ( time - * sec ) ;
1001+ * fsec = time - * sec ;
10021002#endif
1003-
1004- return ;
10051003}/* dt2time() */
10061004
10071005
@@ -1038,35 +1036,62 @@ timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, char **tzn,
10381036#endif
10391037}
10401038
1041- time = dt ;
10421039#ifdef HAVE_INT64_TIMESTAMP
1040+ time = dt ;
10431041TMODULO (time ,date ,USECS_PER_DAY );
10441042
10451043if (time < INT64CONST (0 ))
10461044{
10471045time += USECS_PER_DAY ;
10481046date -= 1 ;
10491047}
1048+
1049+ /* add offset to go from J2000 back to standard Julian date */
1050+ date += POSTGRES_EPOCH_JDATE ;
1051+
1052+ /* Julian day routine does not work for negative Julian days */
1053+ if (date < 0 || date > (Timestamp )INT_MAX )
1054+ return -1 ;
1055+
1056+ j2date ((int )date ,& tm -> tm_year ,& tm -> tm_mon ,& tm -> tm_mday );
1057+ dt2time (time ,& tm -> tm_hour ,& tm -> tm_min ,& tm -> tm_sec ,fsec );
10501058#else
1059+ time = dt ;
10511060TMODULO (time ,date , (double )SECS_PER_DAY );
10521061
10531062if (time < 0 )
10541063{
10551064time += SECS_PER_DAY ;
1056- date -= 1 ;
1065+ date -= 1 ;
10571066}
1058- #endif
10591067
10601068/* add offset to go from J2000 back to standard Julian date */
10611069date += POSTGRES_EPOCH_JDATE ;
10621070
1071+ recalc_d :
10631072/* Julian day routine does not work for negative Julian days */
1064- if (date < 0 || date > (Timestamp )INT_MAX )
1073+ if (date < 0 || date > (Timestamp )INT_MAX )
10651074return -1 ;
10661075
10671076j2date ((int )date ,& tm -> tm_year ,& tm -> tm_mon ,& tm -> tm_mday );
1077+ recalc_t :
10681078dt2time (time ,& tm -> tm_hour ,& tm -> tm_min ,& tm -> tm_sec ,fsec );
10691079
1080+ * fsec = TSROUND (* fsec );
1081+ /* roundoff may need to propagate to higher-order fields */
1082+ if (* fsec >=1.0 )
1083+ {
1084+ time = ceil (time );
1085+ if (time >= (double )SECS_PER_DAY )
1086+ {
1087+ time = 0 ;
1088+ date += 1 ;
1089+ gotorecalc_d ;
1090+ }
1091+ gotorecalc_t ;
1092+ }
1093+ #endif
1094+
10701095/* Done if no TZ conversion wanted */
10711096if (tzp == NULL )
10721097{
@@ -1216,9 +1241,17 @@ interval2tm(Interval span, struct pg_tm *tm, fsec_t *fsec)
12161241tm -> tm_sec = time /USECS_PER_SEC ;
12171242* fsec = time - (tm -> tm_sec * USECS_PER_SEC );
12181243#else
1244+ recalc :
12191245TMODULO (time ,tm -> tm_hour , (double )SECS_PER_HOUR );
12201246TMODULO (time ,tm -> tm_min , (double )SECS_PER_MINUTE );
12211247TMODULO (time ,tm -> tm_sec ,1.0 );
1248+ time = TSROUND (time );
1249+ /* roundoff may need to propagate to higher-order fields */
1250+ if (time >=1.0 )
1251+ {
1252+ time = ceil (span .time );
1253+ gotorecalc ;
1254+ }
12221255* fsec = time ;
12231256#endif
12241257
@@ -1237,8 +1270,7 @@ tm2interval(struct pg_tm *tm, fsec_t fsec, Interval *span)
12371270#else
12381271span -> time = (((tm -> tm_hour * (double )MINS_PER_HOUR )+
12391272tm -> tm_min )* (double )SECS_PER_MINUTE )+
1240- tm -> tm_sec ;
1241- span -> time = JROUND (span -> time + fsec );
1273+ tm -> tm_sec + fsec ;
12421274#endif
12431275
12441276return 0 ;
@@ -1266,7 +1298,6 @@ dt2local(Timestamp dt, int tz)
12661298dt -= (tz * USECS_PER_SEC );
12671299#else
12681300dt -= tz ;
1269- dt = JROUND (dt );
12701301#endif
12711302return dt ;
12721303}/* dt2local() */
@@ -1901,11 +1932,7 @@ timestamp_mi(PG_FUNCTION_ARGS)
19011932(errcode (ERRCODE_DATETIME_VALUE_OUT_OF_RANGE ),
19021933errmsg ("cannot subtract infinite timestamps" )));
19031934
1904- #ifdef HAVE_INT64_TIMESTAMP
19051935result -> time = dt1 - dt2 ;
1906- #else
1907- result -> time = JROUND (dt1 - dt2 );
1908- #endif
19091936
19101937result -> month = 0 ;
19111938result -> day = 0 ;
@@ -2224,11 +2251,7 @@ interval_pl(PG_FUNCTION_ARGS)
22242251
22252252result -> month = span1 -> month + span2 -> month ;
22262253result -> day = span1 -> day + span2 -> day ;
2227- #ifdef HAVE_INT64_TIMESTAMP
22282254result -> time = span1 -> time + span2 -> time ;
2229- #else
2230- result -> time = JROUND (span1 -> time + span2 -> time );
2231- #endif
22322255
22332256PG_RETURN_INTERVAL_P (result );
22342257}
@@ -2244,11 +2267,7 @@ interval_mi(PG_FUNCTION_ARGS)
22442267
22452268result -> month = span1 -> month - span2 -> month ;
22462269result -> day = span1 -> day - span2 -> day ;
2247- #ifdef HAVE_INT64_TIMESTAMP
22482270result -> time = span1 -> time - span2 -> time ;
2249- #else
2250- result -> time = JROUND (span1 -> time - span2 -> time );
2251- #endif
22522271
22532272PG_RETURN_INTERVAL_P (result );
22542273}
@@ -2280,7 +2299,7 @@ interval_mul(PG_FUNCTION_ARGS)
22802299#ifdef HAVE_INT64_TIMESTAMP
22812300result -> time = rint (span -> time * factor + day_remainder * USECS_PER_DAY );
22822301#else
2283- result -> time = JROUND ( span -> time * factor + day_remainder * SECS_PER_DAY ) ;
2302+ result -> time = span -> time * factor + day_remainder * SECS_PER_DAY ;
22842303#endif
22852304
22862305result = DatumGetIntervalP (DirectFunctionCall1 (interval_justify_hours ,
@@ -2332,7 +2351,6 @@ interval_div(PG_FUNCTION_ARGS)
23322351result -> time += rint (day_remainder * USECS_PER_DAY );
23332352#else
23342353result -> time += day_remainder * SECS_PER_DAY ;
2335- result -> time = JROUND (result -> time );
23362354#endif
23372355
23382356result = DatumGetIntervalP (DirectFunctionCall1 (interval_justify_hours ,