]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-88473: Implement fast path in date.today() for date types (#130980)
authorStan Ulbrych <89152624+StanFromIreland@users.noreply.github.com>
Tue, 16 Sep 2025 09:28:54 +0000 (10:28 +0100)
committerGitHub <noreply@github.com>
Tue, 16 Sep 2025 09:28:54 +0000 (10:28 +0100)
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
Misc/NEWS.d/next/Library/2025-03-08-17-07-00.gh-issue-88473.qg23g8.rst [new file with mode: 0644]
Modules/_datetimemodule.c

diff --git a/Misc/NEWS.d/next/Library/2025-03-08-17-07-00.gh-issue-88473.qg23g8.rst b/Misc/NEWS.d/next/Library/2025-03-08-17-07-00.gh-issue-88473.qg23g8.rst
new file mode 100644 (file)
index 0000000..f38ec8e
--- /dev/null
@@ -0,0 +1,3 @@
+Implement a fast path for :class:`datetime.date` objects in :func:`datetime.date.today`
+which results in a 5x performance gain while proper subclasses retain their
+previous performance.
index 329be68d5b8285d4a4d91d49300713d36a73e40b..12d316985fceb93c6aeb1775b1e6cd5955c017ab 100644 (file)
@@ -3291,19 +3291,31 @@ static PyObject *
 datetime_date_today_impl(PyTypeObject *type)
 /*[clinic end generated code: output=d5474697df6b251c input=21688afa289c0a06]*/
 {
-    PyObject *time;
-    PyObject *result;
-    time = time_time();
-    if (time == NULL)
+    /* Use C implementation to boost performance for date type */
+    if (type == &PyDateTime_DateType) {
+        struct tm tm;
+        time_t t;
+        time(&t);
+
+        if (_PyTime_localtime(t, &tm) != 0) {
+            return NULL;
+        }
+
+        return new_date_ex(tm.tm_year + 1900,
+                           tm.tm_mon + 1,
+                           tm.tm_mday,
+                           type);
+    }
+
+    PyObject *time = time_time();
+    if (time == NULL) {
         return NULL;
+    }
 
-    /* Note well:  today() is a class method, so this may not call
-     * date.fromtimestamp.  For example, it may call
-     * datetime.fromtimestamp.  That's why we need all the accuracy
-     * time.time() delivers; if someone were gonzo about optimization,
-     * date.today() could get away with plain C time().
+    /* Note well: since today() is a class method, it may not call
+     * date.fromtimestamp, e.g., it may call datetime.fromtimestamp.
      */
-    result = PyObject_CallMethodOneArg((PyObject*)type, &_Py_ID(fromtimestamp), time);
+    PyObject *result = PyObject_CallMethodOneArg((PyObject*)type, &_Py_ID(fromtimestamp), time);
     Py_DECREF(time);
     return result;
 }