Commit 10cadce4 authored by Tim Peters's avatar Tim Peters

Reimplemented datetime.now() to be useful.

parent 250684dd
...@@ -525,19 +525,25 @@ Other constructors, all class methods: ...@@ -525,19 +525,25 @@ Other constructors, all class methods:
See also \method{now()}, \method{fromtimestamp()}. See also \method{now()}, \method{fromtimestamp()}.
\end{methoddesc} \end{methoddesc}
\begin{methoddesc}{now}{} \begin{methoddesc}{now(tz=None)}{}
Return the current local datetime. This is like \method{today()}, Return the current local date and time. If optional argument
but, if possible, supplies more precision than can be gotten from \var{tz} is \code{None} or not specified, this is like
going through a \function{time.time()} timestamp (for example, \method{today()}, but, if possible, supplies more precision than can
this may be possible on platforms that supply the C be gotten from going through a \function{time.time()} timestamp (for
example, this may be possible on platforms supplying the C
\cfunction{gettimeofday()} function). \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
zone. In this case the result is equivalent to
\code{\var{tz}.fromutc(datetime.utcnow().replace(tzinfo=\var{tz})}.
See also \method{today()}, \method{utcnow()}. See also \method{today()}, \method{utcnow()}.
\end{methoddesc} \end{methoddesc}
\begin{methoddesc}{utcnow}{} \begin{methoddesc}{utcnow}{}
Return the current UTC datetime, with \member{tzinfo} \code{None}. Return the current UTC date and time, with \member{tzinfo} \code{None}.
This is like \method{now()}, but This is like \method{now()}, but returns the current UTC date and time,
returns the current UTC date and time. as a naive \class{datetime} object.
See also \method{now()}. See also \method{now()}.
\end{methoddesc} \end{methoddesc}
......
...@@ -2228,7 +2228,7 @@ class TestDateTimeTZ(TestDateTime, TZInfoBase): ...@@ -2228,7 +2228,7 @@ class TestDateTimeTZ(TestDateTime, TZInfoBase):
# Try with and without naming the keyword. # Try with and without naming the keyword.
off42 = FixedOffset(42, "42") off42 = FixedOffset(42, "42")
another = meth(off42) another = meth(off42)
again = meth(tzinfo=off42) again = meth(tz=off42)
self.failUnless(another.tzinfo is again.tzinfo) self.failUnless(another.tzinfo is again.tzinfo)
self.assertEqual(another.utcoffset(), timedelta(minutes=42)) self.assertEqual(another.utcoffset(), timedelta(minutes=42))
# Bad argument with and w/o naming the keyword. # Bad argument with and w/o naming the keyword.
...@@ -2239,6 +2239,24 @@ class TestDateTimeTZ(TestDateTime, TZInfoBase): ...@@ -2239,6 +2239,24 @@ class TestDateTimeTZ(TestDateTime, TZInfoBase):
# Too many args. # Too many args.
self.assertRaises(TypeError, meth, off42, off42) self.assertRaises(TypeError, meth, off42, off42)
# We don't know which time zone we're in, and don't have a tzinfo
# class to represent it, so seeing whether a tz argument actually
# does a conversion is tricky.
weirdtz = FixedOffset(timedelta(hours=15, minutes=58), "weirdtz", 0)
utc = FixedOffset(0, "utc", 0)
for dummy in range(3):
now = datetime.now(weirdtz)
self.failUnless(now.tzinfo is weirdtz)
utcnow = datetime.utcnow().replace(tzinfo=utc)
now2 = utcnow.astimezone(weirdtz)
if abs(now - now2) < timedelta(seconds=30):
break
# Else the code is broken, or more than 30 seconds passed between
# calls; assuming the latter, just try again.
else:
# Three strikes and we're out.
self.fail("utcnow(), now(tz), or astimezone() may be broken")
def test_tzinfo_fromtimestamp(self): def test_tzinfo_fromtimestamp(self):
import time import time
meth = self.theclass.fromtimestamp meth = self.theclass.fromtimestamp
...@@ -2448,7 +2466,7 @@ class TestDateTimeTZ(TestDateTime, TZInfoBase): ...@@ -2448,7 +2466,7 @@ class TestDateTimeTZ(TestDateTime, TZInfoBase):
f44m = FixedOffset(44, "44") f44m = FixedOffset(44, "44")
fm5h = FixedOffset(-timedelta(hours=5), "m300") fm5h = FixedOffset(-timedelta(hours=5), "m300")
dt = self.theclass.now(tzinfo=f44m) dt = self.theclass.now(tz=f44m)
self.failUnless(dt.tzinfo is f44m) self.failUnless(dt.tzinfo is f44m)
# Replacing with degenerate tzinfo raises an exception. # Replacing with degenerate tzinfo raises an exception.
self.assertRaises(ValueError, dt.astimezone, fnone) self.assertRaises(ValueError, dt.astimezone, fnone)
......
...@@ -82,6 +82,17 @@ Extension modules ...@@ -82,6 +82,17 @@ Extension modules
creativity of political time zone fiddling appears unbounded -- fromutc() creativity of political time zone fiddling appears unbounded -- fromutc()
allows the highly motivated to emulate any scheme expressible in Python. allows the highly motivated to emulate any scheme expressible in Python.
datetime.now(): The optional tzinfo argument was undocumented (that's
repaired), and its name was changed to tz ("tzinfo" is overloaded enough
already). With a tz argument, now(tz) used to return the local date
and time, and attach tz to it, without any conversion of date and time
members. This was less than useful. Now now(tz) returns the current
date and time as local time in tz's time zone, akin to
tz.fromutc(datetime.utcnow().replace(tzinfo=utc))
where "utc" is an instance of a tzinfo subclass modeling UTC. Without
a tz argument, now() continues to return the current local date and time,
as a naive datetime object.
The constructors building a datetime from a timestamp could raise The constructors building a datetime from a timestamp could raise
ValueError if the platform C localtime()/gmtime() inserted "leap ValueError if the platform C localtime()/gmtime() inserted "leap
seconds". Leap seconds are ignored now. On such platforms, it's seconds". Leap seconds are ignored now. On such platforms, it's
......
...@@ -3666,15 +3666,25 @@ datetime_best_possible(PyObject *cls, TM_FUNC f, PyObject *tzinfo) ...@@ -3666,15 +3666,25 @@ datetime_best_possible(PyObject *cls, TM_FUNC f, PyObject *tzinfo)
static PyObject * static PyObject *
datetime_now(PyObject *cls, PyObject *args, PyObject *kw) datetime_now(PyObject *cls, PyObject *args, PyObject *kw)
{ {
PyObject *self = NULL; PyObject *self;
PyObject *tzinfo = Py_None; PyObject *tzinfo = Py_None;
static char *keywords[] = {"tzinfo", NULL}; static char *keywords[] = {"tz", NULL};
if (PyArg_ParseTupleAndKeywords(args, kw, "|O:now", keywords, if (! PyArg_ParseTupleAndKeywords(args, kw, "|O:now", keywords,
&tzinfo)) { &tzinfo))
if (check_tzinfo_subclass(tzinfo) < 0) return NULL;
return NULL; if (check_tzinfo_subclass(tzinfo) < 0)
self = datetime_best_possible(cls, localtime, tzinfo); return NULL;
self = datetime_best_possible(cls,
tzinfo == Py_None ? localtime : gmtime,
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; return self;
} }
......
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