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.
This commit is contained in:
parent
10cadce41e
commit
2a44a8d332
|
@ -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, ×tamp, &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, ×tamp, &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,
|
||||
|
|
Loading…
Reference in New Issue