diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index a59b59211b2e8ba6118c182d344c75b3c4892d37..942bd83c782c51cdee4782d8109e0d38af2c4201 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/func.sgml,v 1.159 2003/07/15 19:19:55 tgl Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/func.sgml,v 1.160 2003/07/17 00:55:36 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -5016,16 +5016,16 @@ SELECT EXTRACT(SECOND FROM TIME '17:12:28.5');
 </screen>
       </listitem>
      </varlistentry>
-<!--
      <varlistentry>
       <term><literal>timezone</literal></term>
       <listitem>
        <para>
-        The time zone offset. XXX But in what units?
+        The time zone offset from UTC, measured in seconds.  Positive values
+	correspond to time zones east of UTC, negative values to
+	zones west of UTC.
        </para>
       </listitem>
      </varlistentry>
--->
 
      <varlistentry>
       <term><literal>timezone_hour</literal></term>
diff --git a/doc/src/sgml/ref/set.sgml b/doc/src/sgml/ref/set.sgml
index 7a5c8b51fb7ee91e5a95999398b9c520b81ad078..08ea5f3c2f4b18e3c01657805ea4dde84ecdc3b1 100644
--- a/doc/src/sgml/ref/set.sgml
+++ b/doc/src/sgml/ref/set.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/ref/set.sgml,v 1.78 2003/07/15 19:19:56 tgl Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/ref/set.sgml,v 1.79 2003/07/17 00:55:36 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -182,16 +182,16 @@ SELECT setseed(<replaceable>value</replaceable>);
          </listitem>
         </varlistentry>
         <varlistentry>
-         <term><literal>7</literal></term>
+         <term><literal>-7</literal></term>
          <listitem>
           <para>
            The time zone 7 hours west from UTC (equivalent
-           to PDT).  Negative values are east from UTC.
+           to PDT).  Positive values are east from UTC.
           </para>
          </listitem>
         </varlistentry>
         <varlistentry>
-         <term><literal>INTERVAL '08:00' HOUR TO MINUTE</literal></term>
+         <term><literal>INTERVAL '-08:00' HOUR TO MINUTE</literal></term>
          <listitem>
           <para>
            The time zone 8 hours west from UTC (equivalent
@@ -205,7 +205,7 @@ SELECT setseed(<replaceable>value</replaceable>);
          <listitem>
           <para>
            Set the time zone to your local time zone (the one that
-           your operating system defaults to).
+           the server's operating system defaults to).
           </para>
          </listitem>
         </varlistentry>
diff --git a/doc/src/sgml/release.sgml b/doc/src/sgml/release.sgml
index 5164f7155a126c81a62bbbeda56111f43cf9e014..3829d1eb8313d75c51b97439d311d3745f8cf063 100644
--- a/doc/src/sgml/release.sgml
+++ b/doc/src/sgml/release.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.197 2003/07/15 19:19:55 tgl Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.198 2003/07/17 00:55:36 tgl Exp $
 -->
 
 <appendix id="release">
@@ -24,6 +24,8 @@ CDATA means the content is "SGML-free", so you can write without
 worries about funny characters.
 -->
 <literallayout><![CDATA[
+EXTRACT(TIMEZONE) and SET/SHOW TIMEZONE now follow SQL sign convention
+  (positive = east of UTC)
 Output of SHOW DATESTYLE is now in the same format accepted by SET DATESTYLE
 PL/Python is now an untrusted language, and is renamed to 'plpythonu'
 Dollar sign ($) is no longer allowed in operator names
diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c
index 41bc3f58bc26e210171a44caf05baba3bd1554f8..9a525b14b89c52e9e48700a1d332f5ae5fb1357c 100644
--- a/src/backend/commands/variable.c
+++ b/src/backend/commands/variable.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.81 2003/07/15 19:34:43 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/variable.c,v 1.82 2003/07/17 00:55:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -429,7 +429,8 @@ assign_timezone(const char *value, bool doit, bool interactive)
 		}
 		if (doit)
 		{
-			CTimeZone = interval->time;
+			/* Here we change from SQL to Unix sign convention */
+			CTimeZone = - interval->time;
 			HasCTZSet = true;
 		}
 		pfree(interval);
@@ -444,7 +445,8 @@ assign_timezone(const char *value, bool doit, bool interactive)
 		{
 			if (doit)
 			{
-				CTimeZone = hours * 3600;
+				/* Here we change from SQL to Unix sign convention */
+				CTimeZone = - hours * 3600;
 				HasCTZSet = true;
 			}
 		}
@@ -557,7 +559,8 @@ assign_timezone(const char *value, bool doit, bool interactive)
 		return NULL;
 
 	if (HasCTZSet)
-		snprintf(result, sizeof(tzbuf), "%.5f", (double) CTimeZone / 3600.0);
+		snprintf(result, sizeof(tzbuf), "%.5f",
+				 (double) (-CTimeZone) / 3600.0);
 	else if (tzbuf[0] == 'T')
 		strcpy(result, tzbuf + 3);
 	else
@@ -579,7 +582,7 @@ show_timezone(void)
 		Interval	interval;
 
 		interval.month = 0;
-		interval.time = CTimeZone;
+		interval.time = - CTimeZone;
 
 		tzn = DatumGetCString(DirectFunctionCall1(interval_out,
 										  IntervalPGetDatum(&interval)));
diff --git a/src/backend/utils/adt/date.c b/src/backend/utils/adt/date.c
index fa03b577891e5b062925d9cc3ab3958dad68677d..ea1768be79de8833819b87e76d72b9b590b0f24b 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.83 2003/06/16 18:56:45 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.84 2003/07/17 00:55:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2031,17 +2031,18 @@ timetz_part(PG_FUNCTION_ARGS)
 		switch (val)
 		{
 			case DTK_TZ:
-				result = tz;
+				result = -tz;
 				break;
 
 			case DTK_TZ_MINUTE:
-				result = tz / 60;
-				TMODULO(result, dummy, 60e0);
+				result = -tz;
+				result /= 60;
+				FMODULO(result, dummy, 60e0);
 				break;
 
 			case DTK_TZ_HOUR:
-				dummy = tz;
-				TMODULO(dummy, result, 3600e0);
+				dummy = -tz;
+				FMODULO(dummy, result, 3600e0);
 				break;
 
 			case DTK_MICROSEC:
diff --git a/src/backend/utils/adt/nabstime.c b/src/backend/utils/adt/nabstime.c
index fe14c9bec4f2abbcdfc4dda89a8d788a6e8736a7..88943a7667609e25ed03c20a7760c221d7c25d88 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.108 2003/05/12 23:08:50 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.109 2003/07/17 00:55:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -825,12 +825,14 @@ reltimesend(PG_FUNCTION_ARGS)
 static void
 reltime2tm(RelativeTime time, struct tm * tm)
 {
-	TMODULO(time, tm->tm_year, 31557600);
-	TMODULO(time, tm->tm_mon, 2592000);
-	TMODULO(time, tm->tm_mday, 86400);
-	TMODULO(time, tm->tm_hour, 3600);
-	TMODULO(time, tm->tm_min, 60);
-	TMODULO(time, tm->tm_sec, 1);
+	double	dtime = time;
+
+	FMODULO(dtime, tm->tm_year, 31557600);
+	FMODULO(dtime, tm->tm_mon, 2592000);
+	FMODULO(dtime, tm->tm_mday, 86400);
+	FMODULO(dtime, tm->tm_hour, 3600);
+	FMODULO(dtime, tm->tm_min, 60);
+	FMODULO(dtime, tm->tm_sec, 1);
 }
 
 
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index 6cf4f3667cf734b8b2f9d994df448b5528245ec5..4ee6e953240f2900c74527544252fc0d5b33c175 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.85 2003/07/04 18:21:13 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.86 2003/07/17 00:55:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -3080,17 +3080,18 @@ timestamptz_part(PG_FUNCTION_ARGS)
 		switch (val)
 		{
 			case DTK_TZ:
-				result = tz;
+				result = -tz;
 				break;
 
 			case DTK_TZ_MINUTE:
-				result = tz / 60;
-				TMODULO(result, dummy, 60e0);
+				result = -tz;
+				result /= 60;
+				FMODULO(result, dummy, 60e0);
 				break;
 
 			case DTK_TZ_HOUR:
-				dummy = tz;
-				TMODULO(dummy, result, 3600e0);
+				dummy = -tz;
+				FMODULO(dummy, result, 3600e0);
 				break;
 
 			case DTK_MICROSEC:
diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h
index 213d25813330f5902fe205b34612668b5ccf3701..cfe065ffcf09fc7f06211f94b6ce07802d2732a8 100644
--- a/src/include/miscadmin.h
+++ b/src/include/miscadmin.h
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: miscadmin.h,v 1.125 2003/06/27 19:08:38 tgl Exp $
+ * $Id: miscadmin.h,v 1.126 2003/07/17 00:55:37 tgl Exp $
  *
  * NOTES
  *	  some of the information in this file should be moved to
@@ -147,7 +147,9 @@ extern DLLIMPORT Oid MyDatabaseId;
  * EuroDates if client prefers dates interpreted and written w/European conventions.
  *
  * HasCTZSet is true if user has set timezone as a numeric offset from UTC.
- * If so, CTimeZone is the timezone offset in seconds.
+ * If so, CTimeZone is the timezone offset in seconds (using the Unix-ish
+ * sign convention, ie, positive offset is west of UTC, rather than the
+ * SQL-ish convention that positive is east of UTC).
  */
 
 #define MAXTZLEN		10		/* max TZ name len, not counting tr. null */
diff --git a/src/include/utils/datetime.h b/src/include/utils/datetime.h
index 7623095f09cd54b722b58357ab5acda2191e1b20..4a9443e17500d77011e28c8f9a2b910c740f77d4 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.39 2003/05/18 01:06:26 tgl Exp $
+ * $Id: datetime.h,v 1.40 2003/07/17 00:55:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -196,12 +196,23 @@ typedef struct
 } datetkn;
 
 
-/* TMODULO()
+/* FMODULO()
  * Macro to replace modf(), which is broken on some platforms.
  * t = input and remainder
  * q = integer part
  * u = divisor
  */
+#define FMODULO(t,q,u) \
+do { \
+	q = ((t < 0) ? ceil(t / u): floor(t / u)); \
+	if (q != 0) t -= rint(q * u); \
+} while(0)
+
+/* TMODULO()
+ * Like FMODULO(), but work on the timestamp datatype (either int64 or float8).
+ * We assume that int64 follows the C99 semantics for division (negative
+ * quotients truncate towards zero).
+ */
 #ifdef HAVE_INT64_TIMESTAMP
 #define TMODULO(t,q,u) \
 do { \
@@ -211,7 +222,7 @@ do { \
 #else
 #define TMODULO(t,q,u) \
 do { \
-	q = ((t < 0)? ceil(t / u): floor(t / u)); \
+	q = ((t < 0) ? ceil(t / u): floor(t / u)); \
 	if (q != 0) t -= rint(q * u); \
 } while(0)
 #endif
diff --git a/src/interfaces/ecpg/pgtypeslib/dt.h b/src/interfaces/ecpg/pgtypeslib/dt.h
index 5f68620233756db122dd874fe3d6c82ffb907208..185f0b0c9489e3ab51b859f23563498cfc19de6a 100644
--- a/src/interfaces/ecpg/pgtypeslib/dt.h
+++ b/src/interfaces/ecpg/pgtypeslib/dt.h
@@ -183,12 +183,23 @@ typedef struct
 } datetkn;
 
 
-/* TMODULO()
+/* FMODULO()
  * Macro to replace modf(), which is broken on some platforms.
  * t = input and remainder
  * q = integer part
  * u = divisor
  */
+#define FMODULO(t,q,u) \
+do { \
+	q = ((t < 0) ? ceil(t / u): floor(t / u)); \
+	if (q != 0) t -= rint(q * u); \
+} while(0)
+
+/* TMODULO()
+ * Like FMODULO(), but work on the timestamp datatype (either int64 or float8).
+ * We assume that int64 follows the C99 semantics for division (negative
+ * quotients truncate towards zero).
+ */
 #ifdef HAVE_INT64_TIMESTAMP
 #define TMODULO(t,q,u) \
 do { \
@@ -198,7 +209,7 @@ do { \
 #else
 #define TMODULO(t,q,u) \
 do { \
-	q = ((t < 0)? ceil(t / u): floor(t / u)); \
+	q = ((t < 0) ? ceil(t / u): floor(t / u)); \
 	if (q != 0) t -= rint(q * u); \
 } while(0)
 #endif