Browse Source

Fixed #34070 -- Added subsecond support to Now() on SQLite and MySQL.

Lily Foote 2 years ago
parent
commit
649b28eab6

+ 1 - 1
django/db/backends/mysql/features.py

@@ -81,7 +81,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
             "swedish_ci": f"{charset}_swedish_ci",
         }
 
-    test_now_utc_template = "UTC_TIMESTAMP"
+    test_now_utc_template = "UTC_TIMESTAMP(6)"
 
     @cached_property
     def django_test_skips(self):

+ 13 - 0
django/db/models/functions/datetime.py

@@ -223,6 +223,19 @@ class Now(Func):
             compiler, connection, template="STATEMENT_TIMESTAMP()", **extra_context
         )
 
+    def as_mysql(self, compiler, connection, **extra_context):
+        return self.as_sql(
+            compiler, connection, template="CURRENT_TIMESTAMP(6)", **extra_context
+        )
+
+    def as_sqlite(self, compiler, connection, **extra_context):
+        return self.as_sql(
+            compiler,
+            connection,
+            template="STRFTIME('%%Y-%%m-%%d %%H:%%M:%%f', 'NOW')",
+            **extra_context,
+        )
+
 
 class TruncBase(TimezoneMixin, Transform):
     kind = None

+ 5 - 0
docs/ref/models/database-functions.txt

@@ -495,6 +495,11 @@ Usage example::
     ``Now()`` uses ``STATEMENT_TIMESTAMP`` instead. If you need the transaction
     timestamp, use :class:`django.contrib.postgres.functions.TransactionNow`.
 
+.. versionchanged:: 4.2
+
+    Support for microsecond precision on MySQL and millisecond precision on
+    SQLite were added.
+
 ``Trunc``
 ---------
 

+ 3 - 0
docs/releases/4.2.txt

@@ -223,6 +223,9 @@ Models
   the text value of a key, index, or path transform of
   :class:`~django.db.models.JSONField`.
 
+* :class:`~django.db.models.functions.Now` now supports microsecond precision
+  on MySQL and millisecond precision on SQLite.
+
 Requests and Responses
 ~~~~~~~~~~~~~~~~~~~~~~
 

+ 17 - 1
tests/db_functions/datetime/test_now.py

@@ -1,6 +1,8 @@
 from datetime import datetime, timedelta
 
-from django.db.models.functions import Now
+from django.db import connection
+from django.db.models import TextField
+from django.db.models.functions import Cast, Now
 from django.test import TestCase
 from django.utils import timezone
 
@@ -47,3 +49,17 @@ class NowTests(TestCase):
             ["How to Time Travel"],
             lambda a: a.title,
         )
+
+    def test_microseconds(self):
+        Article.objects.create(
+            title="How to Django",
+            text=lorem_ipsum,
+            written=timezone.now(),
+        )
+        now_string = (
+            Article.objects.annotate(now_string=Cast(Now(), TextField()))
+            .get()
+            .now_string
+        )
+        precision = connection.features.time_cast_precision
+        self.assertRegex(now_string, rf"^.*\.\d{{1,{precision}}}")