Opened 6 years ago

Closed 6 years ago

Last modified 6 years ago

#10443 closed (fixed)

Updating Timezone Aware DateTimeField Fails

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

Description

Changeset [10003] sends updates through get_db_prep_save. In the DateTimeField this calls to_python which parses a string. If the string looks like this: 2009-03-09 10:22:49.834296 It works. If the string looks like this: 2009-03-09 10:23:14.439863+00:00 It fails. Attached patch fixes it. But I think we need to actually do something with the timezone info.

Attachments (2)

dt.diff (652 bytes) - added by simonb 6 years ago.
savebug.zip (5.0 KB) - added by simonb 6 years ago.
Example project showing bug when saving tz aware DateTimeField

Download all attachments as: .zip

Change History (8)

Changed 6 years ago by simonb

comment:1 Changed 6 years ago by mtredinnick

  • Component changed from Core framework to Database layer (models, ORM)
  • Needs documentation unset
  • Needs tests set
  • Patch needs improvement set
  • Triage Stage changed from Unreviewed to Accepted

Django's datetime fields are timezone-unaware at the moment. We'll keep it that way for now, for consistency. One day it would be nice to have a datetime-with-timezone field, but that's another ticket (in fact, there are one or two of them open, from memory).

On the subject of the patch, I'm kind of surprised this doesn't need a similar change for saving a model initially, since it uses the same code paths now. Does the same value really work at model creation, but not for updates?

Needs a test case that fails beforehand and passes afterwards.

comment:2 Changed 6 years ago by yorkedork

Malcolm,

I understand that the last thing you need here is anecdotal evidence, but I've experienced the same issue and can verify where binding a tz-aware datetime object to a DateTimeField works on creation but fails on update (here, at least).

A cursory examination leads me to observe that the following bits in UpdateQuery.add_update_fields that were added in [10003]:

if hasattr(val, 'prepare_database_save'):
    val = val.prepare_database_save(field)
else:
    val = field.get_db_prep_save(val)

are _not_ present in InsertQuery.insert_values. When initially setting a DateTimeField a tz-aware datetime object is passed as-is, whereas on update it is passed as a unicode object - which triggers the ValidationError.

comment:3 Changed 6 years ago by simonb

Yes. It really does only happen with updates. I'll attach an example project which demonstrates the issue. The traceback is shown below.

The example uses pytz http://pytz.sourceforge.net/ which greatly takes the tedium out of tz aware applications.

Traceback (most recent call last):

File "test.py", line 12, in <module>

sctz.save()

File "/Users/simonb/src/dj/bugs/savebug/bug/models.py", line 33, in save

super(SomeClassTZ, self).save(force_insert=force_insert, force_update=force_update)

File "/Users/simonb/src/dj/versions/trunk/django/db/models/base.py", line 329, in save

self.save_base(force_insert=force_insert, force_update=force_update)

File "/Users/simonb/src/dj/versions/trunk/django/db/models/base.py", line 380, in save_base

rows = manager.filter(pk=pk_val)._update(values)

File "/Users/simonb/src/dj/versions/trunk/django/db/models/query.py", line 466, in _update

query.add_update_fields(values)

File "/Users/simonb/src/dj/versions/trunk/django/db/models/sql/subqueries.py", line 245, in add_update_fields

val = field.get_db_prep_save(val)

File "/Users/simonb/src/dj/versions/trunk/django/db/models/fields/init.py", line 192, in get_db_prep_save

return self.get_db_prep_value(value)

File "/Users/simonb/src/dj/versions/trunk/django/db/models/fields/init.py", line 562, in get_db_prep_value

return connection.ops.value_to_db_datetime(self.to_python(value))

File "/Users/simonb/src/dj/versions/trunk/django/db/models/fields/init.py", line 540, in to_python

_('Enter a valid date/time in YYYY-MM-DD HH:MM[:ss[.uuuuuu]] format.'))

django.core.exceptions.ValidationError: Enter a valid date/time in YYYY-MM-DD HH:MM[:ss[.uuuuuu]] format.

Changed 6 years ago by simonb

Example project showing bug when saving tz aware DateTimeField

comment:4 Changed 6 years ago by mtredinnick

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

(In [10014]) [1.0.X] Fixed #10443 -- Fixed model attribute updating after r10004.

Adding a get_db_prep_save() call to the UpdateQuery code path meant it
was being called twice if you updated an existing model attribute. This
change removes that double call and also makes TimeField.to_python() a
little more robust for the benefit of the Oracle backend (just in case).

Backport of r10013 from trunk.

comment:5 Changed 6 years ago by ikelly

(In [10024]) Refs #10443: Added Oracle to the #10443 regression test exemption, since we don't yet support it.

comment:6 Changed 6 years ago by ikelly

(In [10025]) [1.0.X] Backport of [10024] from trunk. Refs #10443: Added Oracle to the #10443 regression test exemption, since we don't yet support it.

Note: See TracTickets for help on using tickets.
Back to Top