From d685417fbb8692d5ddee8ce60fc80e6b228c81bf Mon Sep 17 00:00:00 2001 From: Tom Lane <tgl@sss.pgh.pa.us> Date: Fri, 4 Apr 2003 04:50:44 +0000 Subject: [PATCH] Avoid repeated computation of the constants date2j(1970, 1, 1) and date2j(2000, 1, 1). Should make for some marginal speed improvement in date/time operations. --- src/backend/utils/adt/date.c | 22 ++++++------ src/backend/utils/adt/datetime.c | 34 +++++++++++------- src/backend/utils/adt/nabstime.c | 54 +++++++++++++++++++---------- src/backend/utils/adt/pgstatfuncs.c | 13 +------ src/backend/utils/adt/timestamp.c | 29 +++++++--------- src/include/utils/datetime.h | 8 +++-- src/include/utils/nabstime.h | 3 +- 7 files changed, 91 insertions(+), 72 deletions(-) diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c index a31cce92073..5c098a7007a 100644 --- a/src/backend/utils/adt/date.c +++ b/src/backend/utils/adt/date.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.79 2003/02/13 17:04:19 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.80 2003/04/04 04:50:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -91,7 +91,7 @@ date_in(PG_FUNCTION_ARGS) elog(ERROR, "Unrecognized date external representation '%s'", str); } - date = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1)); + date = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE; PG_RETURN_DATEADT(date); } @@ -108,7 +108,7 @@ date_out(PG_FUNCTION_ARGS) *tm = &tt; char buf[MAXDATELEN + 1]; - j2date((date + date2j(2000, 1, 1)), + j2date(date + POSTGRES_EPOCH_JDATE, &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday)); EncodeDateOnly(tm, DateStyle, buf); @@ -256,9 +256,10 @@ date_pl_interval(PG_FUNCTION_ARGS) if (span->month != 0) { - j2date((dateVal + date2j(2000, 1, 1)), &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday)); + j2date(dateVal + POSTGRES_EPOCH_JDATE, + &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday)); tm->tm_mon += span->month; - dateVal = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1); + dateVal = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE; } if (span->time != 0) dateVal += (span->time / 86400e0); @@ -279,9 +280,10 @@ date_mi_interval(PG_FUNCTION_ARGS) if (span->month != 0) { - j2date((dateVal + date2j(2000, 1, 1)), &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday)); + j2date(dateVal + POSTGRES_EPOCH_JDATE, + &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday)); tm->tm_mon -= span->month; - dateVal = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1); + dateVal = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE; } if (span->time != 0) dateVal -= (span->time / 86400e0); @@ -346,7 +348,7 @@ date_timestamptz(PG_FUNCTION_ARGS) struct tm tt, *tm = &tt; - j2date((dateVal + date2j(2000, 1, 1)), + j2date(dateVal + POSTGRES_EPOCH_JDATE, &(tm->tm_year), &(tm->tm_mon), &(tm->tm_mday)); if (IS_VALID_UTIME(tm->tm_year, tm->tm_mon, tm->tm_mday)) @@ -399,7 +401,7 @@ timestamptz_date(PG_FUNCTION_ARGS) if (timestamp2tm(timestamp, &tz, tm, &fsec, &tzn) != 0) elog(ERROR, "Unable to convert timestamp to date"); - result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1); + result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE; PG_RETURN_DATEADT(result); } @@ -431,7 +433,7 @@ abstime_date(PG_FUNCTION_ARGS) default: abstime2tm(abstime, &tz, tm, NULL); - result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1); + result = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE; break; } diff --git a/src/backend/utils/adt/datetime.c b/src/backend/utils/adt/datetime.c index 8978cb534f7..e099245e7c9 100644 --- a/src/backend/utils/adt/datetime.c +++ b/src/backend/utils/adt/datetime.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.102 2003/02/22 05:57:44 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/datetime.c,v 1.103 2003/04/04 04:50:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -648,6 +648,14 @@ j2date(int jd, int *year, int *month, int *day) return; } /* j2date() */ + +/* + * j2day - convert Julian date to day-of-week (0..6 == Sun..Sat) + * + * Note: various places use the locution j2day(date - 1) to produce a + * result according to the convention 0..6 = Mon..Sun. This is a bit of + * a crock, but will work as long as the computation here is just a modulo. + */ int j2day(int date) { @@ -1261,7 +1269,7 @@ DecodeDateTime(char **field, int *ftype, int nf, *dtype = DTK_DATE; GetCurrentDateTime(tm); j2date((date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - 1), - &tm->tm_year, &tm->tm_mon, &tm->tm_mday); + &tm->tm_year, &tm->tm_mon, &tm->tm_mday); tm->tm_hour = 0; tm->tm_min = 0; tm->tm_sec = 0; @@ -1281,7 +1289,7 @@ DecodeDateTime(char **field, int *ftype, int nf, *dtype = DTK_DATE; GetCurrentDateTime(tm); j2date((date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) + 1), - &tm->tm_year, &tm->tm_mon, &tm->tm_mday); + &tm->tm_year, &tm->tm_mon, &tm->tm_mday); tm->tm_hour = 0; tm->tm_min = 0; tm->tm_sec = 0; @@ -1546,8 +1554,7 @@ DetermineLocalTimeZone(struct tm * tm) delta2; time_t mytime; - day = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - - date2j(1970, 1, 1)); + day = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - UNIX_EPOCH_JDATE; mysec = tm->tm_sec + (tm->tm_min + (day * 24 + tm->tm_hour) * 60) * 60; mytime = (time_t) mysec; @@ -1556,8 +1563,8 @@ DetermineLocalTimeZone(struct tm * tm) * and reassemble to get a representation of local time. */ tmp = localtime(&mytime); - day = (date2j(tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday) - - date2j(1970, 1, 1)); + day = date2j(tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday) - + UNIX_EPOCH_JDATE; locsec = tmp->tm_sec + (tmp->tm_min + (day * 24 + tmp->tm_hour) * 60) * 60; /* @@ -1586,8 +1593,8 @@ DetermineLocalTimeZone(struct tm * tm) mysec += delta1; mytime = (time_t) mysec; tmp = localtime(&mytime); - day = (date2j(tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday) - - date2j(1970, 1, 1)); + day = date2j(tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday) - + UNIX_EPOCH_JDATE; locsec = tmp->tm_sec + (tmp->tm_min + (day * 24 + tmp->tm_hour) * 60) * 60; delta2 = mysec - locsec; if (delta2 != delta1) @@ -1595,8 +1602,8 @@ DetermineLocalTimeZone(struct tm * tm) mysec += (delta2 - delta1); mytime = (time_t) mysec; tmp = localtime(&mytime); - day = (date2j(tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday) - - date2j(1970, 1, 1)); + day = date2j(tmp->tm_year + 1900, tmp->tm_mon + 1, tmp->tm_mday) - + UNIX_EPOCH_JDATE; locsec = tmp->tm_sec + (tmp->tm_min + (day * 24 + tmp->tm_hour) * 60) * 60; delta2 = mysec - locsec; } @@ -2360,7 +2367,7 @@ DecodeNumber(int flen, char *str, int fmask, { *tmask = (DTK_M(DOY) | DTK_M(MONTH) | DTK_M(DAY)); tm->tm_yday = val; - j2date((date2j(tm->tm_year, 1, 1) + tm->tm_yday - 1), + j2date(date2j(tm->tm_year, 1, 1) + tm->tm_yday - 1, &tm->tm_year, &tm->tm_mon, &tm->tm_mday); } @@ -3702,6 +3709,9 @@ CheckDateTokenTables(void) { bool ok = true; + Assert(UNIX_EPOCH_JDATE == date2j(1970, 1, 1)); + Assert(POSTGRES_EPOCH_JDATE == date2j(2000, 1, 1)); + ok &= CheckDateTokenTable("datetktbl", datetktbl, szdatetktbl); ok &= CheckDateTokenTable("deltatktbl", deltatktbl, szdeltatktbl); ok &= CheckDateTokenTable("australian_datetktbl", diff --git a/src/backend/utils/adt/nabstime.c b/src/backend/utils/adt/nabstime.c index 8a75bdffbee..ac63b2966eb 100644 --- a/src/backend/utils/adt/nabstime.c +++ b/src/backend/utils/adt/nabstime.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.105 2003/03/20 03:34:56 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.106 2003/04/04 04:50:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -85,10 +85,7 @@ static int istinterval(char *i_string, /* * GetCurrentAbsoluteTime() * - * Get the current system time. Set timezone parameters if not specified - * elsewhere. Define HasCTZSet to allow clients to specify the default - * timezone. - * + * Get the current system time (relative to Unix epoch). */ AbsoluteTime GetCurrentAbsoluteTime(void) @@ -100,11 +97,11 @@ GetCurrentAbsoluteTime(void) } -/* GetCurrentAbsoluteTimeUsec() - * Get the current system time. +/* + * GetCurrentAbsoluteTimeUsec() * - * Returns the number of seconds since epoch (January 1 1970 GMT), - * and returns fractional seconds (as # of microseconds) into *usec. + * Get the current system time (relative to Unix epoch), including fractional + * seconds expressed as microseconds. */ AbsoluteTime GetCurrentAbsoluteTimeUsec(int *usec) @@ -119,7 +116,31 @@ GetCurrentAbsoluteTimeUsec(int *usec) } -/* GetCurrentDateTime() +/* + * AbsoluteTimeUsecToTimestampTz() + * + * Convert system time including microseconds to TimestampTz representation. + */ +TimestampTz +AbsoluteTimeUsecToTimestampTz(AbsoluteTime sec, int usec) +{ + TimestampTz result; + +#ifdef HAVE_INT64_TIMESTAMP + result = ((sec - ((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * 86400)) + * INT64CONST(1000000)) + usec; +#else + result = sec - ((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * 86400) + + (usec / 1000000.0); +#endif + + return result; +} + + +/* + * GetCurrentDateTime() + * * Get the transaction start time ("now()") broken down as a struct tm. */ void @@ -131,13 +152,10 @@ GetCurrentDateTime(struct tm * tm) } /* - * GetCurrentAbsoluteTimeUsec() - * - * Get the current system time. Set timezone parameters if not specified - * elsewhere. Define HasCTZSet to allow clients to specify the default - * timezone. + * GetCurrentTimeUsec() * - * Returns the number of seconds since epoch (January 1 1970 GMT) + * Get the transaction start time ("now()") broken down as a struct tm, + * including fractional seconds and timezone offset. */ void GetCurrentTimeUsec(struct tm * tm, fsec_t *fsec, int *tzp) @@ -152,7 +170,7 @@ GetCurrentTimeUsec(struct tm * tm, fsec_t *fsec, int *tzp) #ifdef HAVE_INT64_TIMESTAMP *fsec = usec; #else - *fsec = usec * 1.0e-6; + *fsec = usec / 1000000.0; #endif } @@ -307,7 +325,7 @@ tm2abstime(struct tm * tm, int tz) || tm->tm_sec < 0 || tm->tm_sec > 59) return INVALID_ABSTIME; - day = (date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(1970, 1, 1)); + day = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - UNIX_EPOCH_JDATE; /* check for time out of range */ if ((day < MIN_DAYNUM) || (day > MAX_DAYNUM)) diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c index 787f0226cdc..083bb1374a4 100644 --- a/src/backend/utils/adt/pgstatfuncs.c +++ b/src/backend/utils/adt/pgstatfuncs.c @@ -328,18 +328,7 @@ pg_stat_get_backend_activity_start(PG_FUNCTION_ARGS) if (sec == 0 && usec == 0) PG_RETURN_NULL(); - /* - * This method of converting "Unix time" (sec/usec since epoch) to a - * PostgreSQL timestamp is an ugly hack -- if you fix it, be sure to - * fix the similar hackery in timestamp.c - */ -#ifdef HAVE_INT64_TIMESTAMP - result = (((sec - ((date2j(2000, 1, 1) - date2j(1970, 1, 1)) * 86400)) - * INT64CONST(1000000)) + usec); -#else - result = (sec + (usec * 1.0e-6) - ((date2j(2000, 1, 1) - - date2j(1970, 1, 1)) * 86400)); -#endif + result = AbsoluteTimeUsecToTimestampTz(sec, usec); PG_RETURN_TIMESTAMPTZ(result); } diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c index feaec85b69e..e2f2b2d35b4 100644 --- a/src/backend/utils/adt/timestamp.c +++ b/src/backend/utils/adt/timestamp.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.81 2003/03/20 06:02:59 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.82 2003/04/04 04:50:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -728,12 +728,7 @@ now(PG_FUNCTION_ARGS) sec = GetCurrentTransactionStartTimeUsec(&usec); -#ifdef HAVE_INT64_TIMESTAMP - result = (((sec - ((date2j(2000, 1, 1) - date2j(1970, 1, 1)) * 86400)) - * INT64CONST(1000000)) + usec); -#else - result = (sec + (usec * 1.0e-6) - ((date2j(2000, 1, 1) - date2j(1970, 1, 1)) * 86400)); -#endif + result = AbsoluteTimeUsecToTimestampTz(sec, usec); PG_RETURN_TIMESTAMPTZ(result); } @@ -800,7 +795,7 @@ timestamp2tm(Timestamp dt, int *tzp, struct tm * tm, fsec_t *fsec, char **tzn) struct tm *tx; #endif - date0 = date2j(2000, 1, 1); + date0 = POSTGRES_EPOCH_JDATE; /* * If HasCTZSet is true then we have a brute force time zone @@ -871,9 +866,9 @@ timestamp2tm(Timestamp dt, int *tzp, struct tm * tm, fsec_t *fsec, char **tzn) { #ifdef HAVE_INT64_TIMESTAMP utime = ((dt / INT64CONST(1000000)) - + ((date0 - date2j(1970, 1, 1)) * INT64CONST(86400))); + + ((date0 - UNIX_EPOCH_JDATE) * INT64CONST(86400))); #else - utime = (dt + ((date0 - date2j(1970, 1, 1)) * 86400)); + utime = (dt + ((date0 - UNIX_EPOCH_JDATE) * 86400)); #endif #if defined(HAVE_TM_ZONE) || defined(HAVE_INT_TIMEZONE) @@ -960,7 +955,7 @@ tm2timestamp(struct tm * tm, fsec_t fsec, int *tzp, Timestamp *result) if (!IS_VALID_JULIAN(tm->tm_year, tm->tm_mon, tm->tm_mday)) return -1; - date = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - date2j(2000, 1, 1); + date = date2j(tm->tm_year, tm->tm_mon, tm->tm_mday) - POSTGRES_EPOCH_JDATE; time = time2t(tm->tm_hour, tm->tm_min, tm->tm_sec, fsec); #ifdef HAVE_INT64_TIMESTAMP *result = ((date * INT64CONST(86400000000)) + time); @@ -2675,7 +2670,7 @@ isoweek2date(int woy, int *year, int *mon, int *mday) day4 = date2j(*year, 1, 4); /* day0 == offset to first day of week (Monday) */ - day0 = (j2day(day4 - 1) % 7); + day0 = j2day(day4 - 1); dayn = ((woy - 1) * 7) + (day4 - day0); @@ -2701,7 +2696,7 @@ date2isoweek(int year, int mon, int mday) day4 = date2j(year, 1, 4); /* day0 == offset to first day of week (Monday) */ - day0 = (j2day(day4 - 1) % 7); + day0 = j2day(day4 - 1); /* * We need the first week containing a Thursday, otherwise this day @@ -2709,10 +2704,10 @@ date2isoweek(int year, int mon, int mday) */ if (dayn < (day4 - day0)) { - day4 = date2j((year - 1), 1, 4); + day4 = date2j(year - 1, 1, 4); /* day0 == offset to first day of week (Monday) */ - day0 = (j2day(day4 - 1) % 7); + day0 = j2day(day4 - 1); } result = (((dayn - (day4 - day0)) / 7) + 1); @@ -2723,10 +2718,10 @@ date2isoweek(int year, int mon, int mday) */ if (result >= 53) { - day4 = date2j((year + 1), 1, 4); + day4 = date2j(year + 1, 1, 4); /* day0 == offset to first day of week (Monday) */ - day0 = (j2day(day4 - 1) % 7); + day0 = j2day(day4 - 1); if (dayn >= (day4 - day0)) result = (((dayn - (day4 - day0)) / 7) + 1); diff --git a/src/include/utils/datetime.h b/src/include/utils/datetime.h index 39905ebb15e..3a419615489 100644 --- a/src/include/utils/datetime.h +++ b/src/include/utils/datetime.h @@ -9,7 +9,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: datetime.h,v 1.36 2003/02/20 05:24:55 tgl Exp $ + * $Id: datetime.h,v 1.37 2003/04/04 04:50:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -259,6 +259,10 @@ extern int day_tab[2][13]; || (((y) == UTIME_MAXYEAR) && (((m) < UTIME_MAXMONTH) \ || (((m) == UTIME_MAXMONTH) && ((d) <= UTIME_MAXDAY)))))) +/* Julian-date equivalents of Day 0 in Unix and Postgres reckoning */ +#define UNIX_EPOCH_JDATE 2440588 /* == date2j(1970, 1, 1) */ +#define POSTGRES_EPOCH_JDATE 2451545 /* == date2j(2000, 1, 1) */ + extern void GetCurrentDateTime(struct tm * tm); extern void GetCurrentTimeUsec(struct tm * tm, fsec_t *fsec, int *tzp); @@ -289,7 +293,7 @@ extern int EncodeInterval(struct tm * tm, fsec_t fsec, int style, char *str); extern int DecodeSpecial(int field, char *lowtoken, int *val); extern int DecodeUnits(int field, char *lowtoken, int *val); -extern bool ClearDateCache(bool, bool, bool); +extern bool ClearDateCache(bool newval, bool doit, bool interactive); extern int j2day(int jd); diff --git a/src/include/utils/nabstime.h b/src/include/utils/nabstime.h index d9391366430..0992e1abee1 100644 --- a/src/include/utils/nabstime.h +++ b/src/include/utils/nabstime.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: nabstime.h,v 1.37 2002/09/01 00:58:07 tgl Exp $ + * $Id: nabstime.h,v 1.38 2003/04/04 04:50:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -157,6 +157,7 @@ extern Datum timeofday(PG_FUNCTION_ARGS); /* non-fmgr-callable support routines */ extern AbsoluteTime GetCurrentAbsoluteTime(void); extern AbsoluteTime GetCurrentAbsoluteTimeUsec(int *usec); +extern TimestampTz AbsoluteTimeUsecToTimestampTz(AbsoluteTime sec, int usec); extern void abstime2tm(AbsoluteTime time, int *tzp, struct tm * tm, char **tzn); #endif /* NABSTIME_H */ -- GitLab