Fixed #19716 -- Added support for microseconds with MySQL 5.6.4 and up

Thanks erik@cederstrand.dk for the report and Tim Graham for the review.
This commit is contained in:
Claude Paroz 2014-08-12 18:14:06 +02:00
parent 9e746c13e8
commit 22da5f8817
4 changed files with 42 additions and 8 deletions

View File

@ -79,7 +79,7 @@ def adapt_datetime_with_timezone_support(value, conv):
default_timezone = timezone.get_default_timezone()
value = timezone.make_aware(value, default_timezone)
value = value.astimezone(timezone.utc).replace(tzinfo=None)
return Thing2Literal(value.strftime("%Y-%m-%d %H:%M:%S"), conv)
return Thing2Literal(value.strftime("%Y-%m-%d %H:%M:%S.%f"), conv)
# MySQLdb-1.2.1 returns TIME columns as timedelta -- they are more like
# timedelta in terms of actual behavior as they are signed and include days --
@ -175,7 +175,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
supports_forward_references = False
# XXX MySQL DB-API drivers currently fail on binary data on Python 3.
supports_binary_field = six.PY2
supports_microsecond_precision = False
supports_regex_backreferencing = False
supports_date_lookup_using_string = False
can_introspect_binary_field = False
@ -210,6 +209,10 @@ class DatabaseFeatures(BaseDatabaseFeatures):
"Confirm support for introspected foreign keys"
return self._mysql_storage_engine != 'MyISAM'
@cached_property
def supports_microsecond_precision(self):
return self.connection.mysql_version >= (5, 6, 4)
@cached_property
def has_zoneinfo_database(self):
# MySQL accepts full time zones names (eg. Africa/Nairobi) but rejects

View File

@ -1,4 +1,5 @@
from django.db.backends.creation import BaseDatabaseCreation
from django.utils.functional import cached_property
class DatabaseCreation(BaseDatabaseCreation):
@ -6,7 +7,7 @@ class DatabaseCreation(BaseDatabaseCreation):
# types, as strings. Column-type strings can contain format strings; they'll
# be interpolated against the values of Field.__dict__ before being output.
# If a column type is set to None, it won't be included in the output.
data_types = {
_data_types = {
'AutoField': 'integer AUTO_INCREMENT',
'BinaryField': 'longblob',
'BooleanField': 'bool',
@ -33,6 +34,13 @@ class DatabaseCreation(BaseDatabaseCreation):
'UUIDField': 'char(32)',
}
@cached_property
def data_types(self):
if self.connection.features.supports_microsecond_precision:
return dict(self._data_types, DateTimeField='datetime(6)', TimeField='time(6)')
else:
return self._data_types
def sql_table_creation_suffix(self):
suffix = []
test_settings = self.connection.settings_dict['TEST']

View File

@ -496,11 +496,32 @@ for the field. This affects :class:`~django.db.models.CharField`,
:class:`~django.db.models.SlugField` and
:class:`~django.db.models.CommaSeparatedIntegerField`.
DateTime fields
~~~~~~~~~~~~~~~
.. _mysql-fractional-seconds:
MySQL does not store fractions of seconds. Fractions of seconds are truncated
to zero when the time is stored.
Fractional seconds support for Time and DateTime fields
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MySQL 5.6.4 and later can store fractional seconds, provided that the
column definition includes a fractional indication (e.g. ``DATETIME(6)``).
Earlier versions do not support them at all.
Django will not upgrade existing columns to include fractional seconds if the
database server supports it. If you want to enable them on an existing database,
it's up to you to either manually update the column on the target database, by
executing a command like::
ALTER TABLE `your_table` MODIFY `your_datetime_column` DATETIME(6)
or using a :class:`~django.db.migrations.operations.RunSQL` operation in a
:ref:`data migration <data-migrations>`.
.. versionchanged:: 1.8
Previously, Django truncated fractional seconds from ``datetime`` and
``time`` values when using the MySQL backend. Now it lets the database
decide whether it should drop that part of the value or not. By default, new
``DateTimeField`` or ``TimeField`` columns are now created with fractional
seconds support on MySQL 5.6.4 or later.
``TIMESTAMP`` columns
~~~~~~~~~~~~~~~~~~~~~

View File

@ -166,7 +166,9 @@ Database backends
* The MySQL backend no longer strips microseconds from ``datetime`` values as
MySQL 5.6.4 and up supports fractional seconds depending on the declaration
of the datetime field (when ``DATETIME`` includes fractional precision greater
than 0).
than 0). New datetime database columns created with Django 1.8 and MySQL 5.6.4
and up will support microseconds. See the :ref:`MySQL database notes
<mysql-fractional-seconds>` for more details.
Email
^^^^^