Kaydet (Commit) 2a44a8d3 authored tarafından Tim Peters's avatar Tim Peters

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.
üst 10cadce4
......@@ -534,26 +534,35 @@ Other constructors, all class methods:
\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
......
......@@ -2266,7 +2266,7 @@ class TestDateTimeTZ(TestDateTime, TZInfoBase):
# 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 @@ class TestDateTimeTZ(TestDateTime, TZInfoBase):
# 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).
......
......@@ -93,6 +93,10 @@ Extension modules
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
......
......@@ -3682,8 +3682,7 @@ datetime_now(PyObject *cls, PyObject *args, PyObject *kw)
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 @@ datetime_utcnow(PyObject *cls, PyObject *dummy)
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 @@ static PyMethodDef datetime_methods[] = {
{"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 @@ static PyMethodDef datetime_methods[] = {
{"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,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment