Hello,

On databases that don't support time zones -- SQLite, MySQL, Oracle (*) -- the
implementation of time zone support I added in Django 1.4 defines:

1. A global converter, e.g. `parse_datetime_with_timezone_support` for SQLite,
   which processes values returned by the database for datetime columns and
   returns `datetime.datetime` values. When USE_TZ is True, these are aware
   datetimes with a UTC timezone.

   This was part of the original patch:
   
https://github.com/django/django/commit/9b1cb755a28f020e27d4268c214b25315d4de42e
 
<https://github.com/django/django/commit/9b1cb755a28f020e27d4268c214b25315d4de42e>

2. A global adapter, e.g. `adapt_datetime_with_timezone_support` for SQLite,
   which processes `datetime.datetime` values sent to the database. When
   USE_TZ is True, these are converted to UTC, then the tzinfo attribute is
   stripped.

   This was introduced to fix #17755:
   
https://github.com/django/django/commit/ce88b57b9aca0325e5b90944019f602a92f93475
 
<https://github.com/django/django/commit/ce88b57b9aca0325e5b90944019f602a92f93475>

(*) I believe that Oracle could support time zones like PostgreSQL but Django
    doesn't take advantage of this capability at this time.

This is a poor implementation because converters and adapters are global in
the sqlite3 and MySQLdb modules. Other packages such as iPython are affected
by these global changes: https://code.djangoproject.com/ticket/19738 
<https://code.djangoproject.com/ticket/19738>

I'll keep cx_Oracle outside of this discussion because it has a per-connection
`outputtypehandler` instead of global converters and because Django's Oracle
backend wraps all parameters instead of relying on global adapters.

I think it would be more appropriate to handle all conversions in the ORM.

With the introduction of DatabaseOperations.get_db_converters in Django 1.8,
it seems possible to use per-connection converters instead of global
converters.

With this change, `cursor.execute()` will return naive datetimes where it used
to return aware datetimes. That's backwards incompatible, but that's the goal:
Django shouldn't alter globally the behavior of sqlite3 or MySQLdb cursors.

Replacing adapters is a bit more tricky. Removing them causes the two
regression tests for #17755 to fail. I haven't determined how I can process
parameters passed to QuerySet.raw(), but since that's part of the ORM, I'm
optimistic.

With this change, `cursor.execute()` will ignore the time zone of datetimes in
parameters. This looks acceptable for naive datetimes because Django has been
raising a warning for five versions in that case. However it may result in
silent data corruption for aware datetimes with a time zone other than UTC.
Once again that's inherent to the change. Besides documenting it, I don't
have anything to suggest.

In addition to making Django a better citizen in the Python ecosystem, these
changes will make it possible to interact with third-party databases where
data isn't stored in UTC when USE_TZ is True, a big flaw in the current
support for time zones: https://code.djangoproject.com/ticket/23820 
<https://code.djangoproject.com/ticket/23820>. This will
be a trivial patch once the global converters and adapters are gone.

Do you think the backwards-incompatibilities are acceptable?

-- 
Aymeric.



-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/67976749-8FAD-404F-B0A6-B195EFC900EB%40polytechnique.org.
For more options, visit https://groups.google.com/d/optout.

Reply via email to