Reimplemented datetime.now() to be useful.
authorTim Peters <tim.peters@gmail.com>
Thu, 23 Jan 2003 19:58:02 +0000 (19:58 +0000)
committerTim Peters <tim.peters@gmail.com>
Thu, 23 Jan 2003 19:58:02 +0000 (19:58 +0000)
Doc/lib/libdatetime.tex
Lib/test/test_datetime.py
Misc/NEWS
Modules/datetimemodule.c

index 9133f1e00d44afc8b6e363ea5141e17ebdc955dc..b890024bfa4fcf7317e3604b94afd757b7271c7b 100644 (file)
@@ -525,19 +525,25 @@ Other constructors, all class methods:
   See also \method{now()}, \method{fromtimestamp()}.
 \end{methoddesc}
 
-\begin{methoddesc}{now}{}
-  Return the current local datetime.  This is like \method{today()},
-  but, if possible, supplies more precision than can be gotten from
-  going through a \function{time.time()} timestamp (for example,
-  this may be possible on platforms that supply the C
+\begin{methoddesc}{now(tz=None)}{}
+  Return the current local date and time.  If optional argument
+  \var{tz} is \code{None} or not specified, this is like
+  \method{today()}, but, if possible, supplies more precision than can
+  be gotten from going through a \function{time.time()} timestamp (for
+  example, this may be possible on platforms supplying the C
   \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()}.
 \end{methoddesc}
 
 \begin{methoddesc}{utcnow}{}
-  Return the current UTC datetime, with \member{tzinfo} \code{None}.
-  This is like \method{now()}, but
-  returns the current UTC date and time.
+  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,
+  as a naive \class{datetime} object.
   See also \method{now()}.
 \end{methoddesc}
 
index 88783868db89128ad52423741baaba320da1b9b6..7d503e019e4a9c2b5e243c6f0c2ba0a91c6f0f3f 100644 (file)
@@ -2228,7 +2228,7 @@ class TestDateTimeTZ(TestDateTime, TZInfoBase):
         # Try with and without naming the keyword.
         off42 = FixedOffset(42, "42")
         another = meth(off42)
-        again = meth(tzinfo=off42)
+        again = meth(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.
@@ -2239,6 +2239,24 @@ class TestDateTimeTZ(TestDateTime, TZInfoBase):
         # Too many args.
         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):
         import time
         meth = self.theclass.fromtimestamp
@@ -2448,7 +2466,7 @@ class TestDateTimeTZ(TestDateTime, TZInfoBase):
         f44m = FixedOffset(44, "44")
         fm5h = FixedOffset(-timedelta(hours=5), "m300")
 
-        dt = self.theclass.now(tzinfo=f44m)
+        dt = self.theclass.now(tz=f44m)
         self.failUnless(dt.tzinfo is f44m)
         # Replacing with degenerate tzinfo raises an exception.
         self.assertRaises(ValueError, dt.astimezone, fnone)
index 780bf5ab7bec39d4e8cb49d0924b8dbe44991532..39ebd9360e86666195407aaa06b04b86d7dd0681 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -82,6 +82,17 @@ Extension modules
   creativity of political time zone fiddling appears unbounded -- fromutc()
   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
   ValueError if the platform C localtime()/gmtime() inserted "leap
   seconds".  Leap seconds are ignored now.  On such platforms, it's
index f615f6851b2b64636e36aa237e5eac5cd1c29a9e..d81d5636f7d67f24aec604245334bc477e8f6140 100644 (file)
@@ -3666,15 +3666,25 @@ datetime_best_possible(PyObject *cls, TM_FUNC f, PyObject *tzinfo)
 static PyObject *
 datetime_now(PyObject *cls, PyObject *args, PyObject *kw)
 {
-       PyObject *self = NULL;
+       PyObject *self;
        PyObject *tzinfo = Py_None;
-       static char *keywords[] = {"tzinfo", NULL};
+       static char *keywords[] = {"tz", NULL};
 
-       if (PyArg_ParseTupleAndKeywords(args, kw, "|O:now", keywords,
-                                       &tzinfo)) {
-               if (check_tzinfo_subclass(tzinfo) < 0)
-                       return NULL;
-               self = datetime_best_possible(cls, localtime, tzinfo);
+       if (! PyArg_ParseTupleAndKeywords(args, kw, "|O:now", keywords,
+                                         &tzinfo))
+               return NULL;
+       if (check_tzinfo_subclass(tzinfo) < 0)
+               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;
 }