Opened 16 months ago

Closed 16 months ago

Last modified 16 months ago

#22549 closed Bug (worksforme)

DateTimeField raises timezone awareness related RuntimeWarnings when it should'nt

Reported by: matias@… Owned by: nobody
Component: Database layer (models, ORM) Version:
Severity: Normal Keywords:
Cc: matias@… Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I've experienced some issues with wrong RuntimeWarnings about naive datetimes being raised when the
datetime I was using was perfectly timezone aware and I think I found the reason why:

In django/db/models/fields/init.py file, inside the definition of DateTimeField.to_python method,
the timezone awareness of a datetime is checked calling the isinstance function.

if isinstance(value, datetime.date):
    value = datetime.datetime(value.year, value.month, value.day)
    if settings.USE_TZ:
        # For backwards compatibility, interpret naive datetimes in
        # local time. This won't work during DST change, but we can't
        # do much about it, so we let the exceptions percolate up the
        # call stack.
        warnings.warn("DateTimeField %s.%s received a naive datetime "
                      "(%s) while time zone support is active." %
                      (self.model.__name__, self.name, value),
                      RuntimeWarning)

Is true that, as said here https://docs.python.org/2.7/library/datetime.html#available-types,
"objects of the date type are always naive", but is wrong to use isinstance since all datetime.datetime
objects are also instances of datetime.date because datetime.datetime is a subclass of datetime.date
(which I think is confusing since breakes the OOP intuition that says that class inheritance should
describe "is a" relationships).

A posible solution is to compare using type(value) == datetime.date or, more clearly, check using django.utils.is_naive

Change History (2)

comment:1 Changed 16 months ago by ramiro

  • Easy pickings unset
  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Triage Stage changed from Unreviewed to Accepted

comment:2 Changed 16 months ago by aaugustin

  • Resolution set to worksforme
  • Status changed from new to closed

Look two lines above -- the complete code is:

        if isinstance(value, datetime.datetime):
            return value
        if isinstance(value, datetime.date):
            # ... stuff you complain about

If value is a datetime.datetime the first branch returns, you don't hit the second branch.

Last edited 16 months ago by aaugustin (previous) (diff)
Note: See TracTickets for help on using tickets.
Back to Top