SF bug 660872:  datetimetz constructors behave counterintuitively (2.3a1).
This gives much the same treatment to datetime.fromtimestamp(stamp, tz) as
the last batch of checkins gave to datetime.now(tz):  do "the obvious"
thing with the tz argument instead of a senseless thing.
diff --git a/Doc/lib/libdatetime.tex b/Doc/lib/libdatetime.tex
index b890024..058d6d5 100644
--- a/Doc/lib/libdatetime.tex
+++ b/Doc/lib/libdatetime.tex
@@ -534,26 +534,35 @@
   \cfunction{gettimeofday()} function).
 
   Else \var{tz} must be an instance of a class \class{tzinfo} subclass,
-  and the current date and time are translated to \var{tz}'s time
+  and the current date and time are converted to \var{tz}'s time
   zone.  In this case the result is equivalent to
-  \code{\var{tz}.fromutc(datetime.utcnow().replace(tzinfo=\var{tz})}.
+  \code{\var{tz}.fromutc(datetime.utcnow().replace(tzinfo=\var{tz}))}.
   See also \method{today()}, \method{utcnow()}.
 \end{methoddesc}
 
 \begin{methoddesc}{utcnow}{}
   Return the current UTC date and time, with \member{tzinfo} \code{None}.
-  This is like \method{now()}, but  returns the current UTC date and time,
+  This is like \method{now()}, but returns the current UTC date and time,
   as a naive \class{datetime} object.
   See also \method{now()}.
 \end{methoddesc}
 
-\begin{methoddesc}{fromtimestamp}{timestamp}
-  Return the local \class{datetime} corresponding to the \POSIX{}
-  timestamp, such as is returned by \function{time.time()}.  This
-  may raise \exception{ValueError}, if the timestamp is out of the
-  range of values supported by the platform C
-  \cfunction{localtime()} function.  It's common for this to be
-  restricted to years in 1970 through 2038.
+\begin{methoddesc}{fromtimestamp}{timestamp, tz=None}
+  Return the local date and time corresponding to the \POSIX{}
+  timestamp, such as is returned by \function{time.time()}.
+  If optional argument \var{tz} is \code{None} or not specified, the
+  timestamp is converted to the platform's local date and time, and
+  the returned \class{datetime} object is naive.
+
+  Else \var{tz} must be an instance of a class \class{tzinfo} subclass,
+  and the timestamp is converted to \var{tz}'s time zone.  In this case
+  the result is equivalent to
+  \code{\var{tz}.fromutc(datetime.utcfromtimestamp(\var{timestamp}).replace(tzinfo=\var{tz}))}.
+
+  \method{fromtimestamp()} may raise \exception{ValueError}, if the
+  timestamp is out of the range of values supported by the platform C
+  \cfunction{localtime()} or \cfunction(gmtime()} functions.  It's common
+  for this to be restricted to years in 1970 through 2038.
   Note that on non-POSIX systems that include leap seconds in their
   notion of a timestamp, leap seconds are ignored by
   \method{fromtimestamp()}, and then it's possible to have two timestamps
diff --git a/Lib/test/test_datetime.py b/Lib/test/test_datetime.py
index 7d503e0..0b9597a 100644
--- a/Lib/test/test_datetime.py
+++ b/Lib/test/test_datetime.py
@@ -2266,7 +2266,7 @@
         # Try with and without naming the keyword.
         off42 = FixedOffset(42, "42")
         another = meth(ts, off42)
-        again = meth(ts, tzinfo=off42)
+        again = meth(ts, tz=off42)
         self.failUnless(another.tzinfo is again.tzinfo)
         self.assertEqual(another.utcoffset(), timedelta(minutes=42))
         # Bad argument with and w/o naming the keyword.
@@ -2279,6 +2279,20 @@
         # Too few args.
         self.assertRaises(TypeError, meth)
 
+        # Try to make sure tz= actually does some conversion.
+        timestamp = 1000000000  #  2001-09-09 01:46:40 UTC, give or take
+        utc = FixedOffset(0, "utc", 0)
+        expected = datetime(2001, 9, 9, 1, 46, 40)
+        got = datetime.utcfromtimestamp(timestamp)
+        # We don't support leap seconds, but maybe the platfrom insists
+        # on using them, so don't demand exact equality).
+        self.failUnless(abs(got - expected) < timedelta(minutes=1))
+
+        est = FixedOffset(-5*60, "est", 0)
+        expected -= timedelta(hours=5)
+        got = datetime.fromtimestamp(timestamp, est).replace(tzinfo=None)
+        self.failUnless(abs(got - expected) < timedelta(minutes=1))
+
     def test_tzinfo_utcnow(self):
         meth = self.theclass.utcnow
         # Ensure it doesn't require tzinfo (i.e., that this doesn't blow up).
diff --git a/Misc/NEWS b/Misc/NEWS
index 39ebd93..bfcddd9 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -93,6 +93,10 @@
   a tz argument, now() continues to return the current local date and time,
   as a naive datetime object.
 
+  datetime.fromtimestamp():  Like datetime.now() above, this had less than
+  useful behavior when the optional tinzo argument was specified.  See
+  also SF bug report <http://www.python.org/sf/660872>.
+
   The constructors building a datetime from a timestamp could raise
   ValueError if the platform C localtime()/gmtime() inserted "leap
   seconds".  Leap seconds are ignored now.  On such platforms, it's
diff --git a/Modules/datetimemodule.c b/Modules/datetimemodule.c
index d81d563..aeccfda 100644
--- a/Modules/datetimemodule.c
+++ b/Modules/datetimemodule.c
@@ -3682,8 +3682,7 @@
 	if (self != NULL && tzinfo != Py_None) {
 		/* Convert UTC to tzinfo's zone. */
 		PyObject *temp = self;
-		self = PyObject_CallMethod(tzinfo, "fromutc",
-					   "O", self);
+		self = PyObject_CallMethod(tzinfo, "fromutc", "O", self);
 		Py_DECREF(temp);
 	}
 	return self;
@@ -3702,17 +3701,26 @@
 static PyObject *
 datetime_fromtimestamp(PyObject *cls, PyObject *args, PyObject *kw)
 {
-	PyObject *self = NULL;
+	PyObject *self;
 	double timestamp;
 	PyObject *tzinfo = Py_None;
-	static char *keywords[] = {"timestamp", "tzinfo", NULL};
+	static char *keywords[] = {"timestamp", "tz", NULL};
 
-	if (PyArg_ParseTupleAndKeywords(args, kw, "d|O:fromtimestamp",
-					keywords, &timestamp, &tzinfo)) {
-		if (check_tzinfo_subclass(tzinfo) < 0)
-			return NULL;
-		self = datetime_from_timestamp(cls, localtime, timestamp,
-					       tzinfo);
+	if (! PyArg_ParseTupleAndKeywords(args, kw, "d|O:fromtimestamp",
+					  keywords, &timestamp, &tzinfo))
+		return NULL;
+	if (check_tzinfo_subclass(tzinfo) < 0)
+		return NULL;
+
+	self = datetime_from_timestamp(cls,
+				       tzinfo == Py_None ? localtime : gmtime,
+				       timestamp,
+				       tzinfo);
+	if (self != NULL && tzinfo != Py_None) {
+		/* Convert UTC to tzinfo's zone. */
+		PyObject *temp = self;
+		self = PyObject_CallMethod(tzinfo, "fromutc", "O", self);
+		Py_DECREF(temp);
 	}
 	return self;
 }
@@ -4404,7 +4412,7 @@
 
 	{"now",         (PyCFunction)datetime_now,
 	 METH_KEYWORDS | METH_CLASS,
-	 PyDoc_STR("[tzinfo] -> new datetime with local day and time.")},
+	 PyDoc_STR("[tz] -> new datetime with tz's locl day and time.")},
 
 	{"utcnow",         (PyCFunction)datetime_utcnow,
 	 METH_NOARGS | METH_CLASS,
@@ -4412,7 +4420,7 @@
 
 	{"fromtimestamp", (PyCFunction)datetime_fromtimestamp,
 	 METH_KEYWORDS | METH_CLASS,
-	 PyDoc_STR("timestamp[, tzinfo] -> local time from POSIX timestamp.")},
+	 PyDoc_STR("timestamp[, tz] -> tz's local time from POSIX timestamp.")},
 
 	{"utcfromtimestamp", (PyCFunction)datetime_utcfromtimestamp,
 	 METH_VARARGS | METH_CLASS,