auto_now=True fields aren't updated on QuerySet.update()

1,372 views
Skip to first unread message

Yo-Yo Ma

unread,
Feb 20, 2012, 1:17:27 PM2/20/12
to Django developers
If you call ``QuerySet.update`` on the following model, you'll get the
results that proceed it:

# models.py
class Person(models.Model):
cool = models.BooleanField(default=False)
updated_on=DateTimeField(auto_now=True)


# django-admin.py shell
>>> from myapp.models import Person
>>>
>>> # Check the updated_on values
>>> Person.objects.values_list('updated_on', flat=True)
[datetime.datetime(2012, 1, 1, 0, 0), datetime.datetime(2012, 1, 1, 0,
0)]
>>> # Fine, just as they are in the fixture. Update ``cool`` field on them
>>> Person.objects.update(cool=True)
2
>>> # Check the updated_on values again
>>> Person.objects.values_list('updated_on', flat=True)
[datetime.datetime(2012, 1, 1, 0, 0), datetime.datetime(2012, 1, 1, 0,
0)]


I understand that ``QuerySet.update`` issues an UPDATE SQL statement,
but Django's code could be modified to include each ``auto_now=True``
field on a model in the UPDATE statement, setting the value to
``datetime.now()`` as it does when you use ``Model.save``.

If this seems reasonable, I'll be happy to write a patch and tests for
it.


Note: I'm using the latest trunk code (1.4 beta), pulled yesterday

Yo-Yo Ma

unread,
Feb 20, 2012, 1:52:34 PM2/20/12
to Django developers
On a related note, the new timezone.now() functionality is used for
``DateTimeField.pre_save`` when ``auto_now=True``, but it isn't used
for ``DateField.pre_save`` or ``TimeField.pre_save``. Is this a bug I
should report, or is there something I'm missing (I'm pretty
uninformed when it comes to UTC and timezone related stuff in Python)?

Aymeric Augustin

unread,
Feb 20, 2012, 1:57:24 PM2/20/12
to django-d...@googlegroups.com

Hello,

This is by design. Timezones don't make sense for date or times, only for datetimes.

See also https://docs.djangoproject.com/en/dev/topics/i18n/timezones/#naive-and-aware-datetime-objects

Best regards,

--
Aymeric.

Anssi Kääriäinen

unread,
Feb 20, 2012, 3:29:29 PM2/20/12
to Django developers
On Feb 20, 8:57 pm, Aymeric Augustin
<aymeric.augus...@polytechnique.org> wrote:
> On 20 févr. 2012, at 19:52, Yo-Yo Ma wrote:
>
> > On a related note, the new timezone.now() functionality is used for
> > ``DateTimeField.pre_save`` when ``auto_now=True``, but it isn't used
> > for ``DateField.pre_save`` or ``TimeField.pre_save``. Is this a bug I
> > should report, or is there something I'm missing (I'm pretty
> > uninformed when it comes to UTC and timezone related stuff in Python)?
>
> Hello,
>
> This is by design. Timezones don't make sense for date or times, only for datetimes.

In [15]: activate('Australia/Sydney')
In [16]: localtime(now()).date()
Out[16]: datetime.date(2012, 2, 21)
In [17]: activate('Europe/Helsinki')
In [18]: localtime(now()).date()
Out[18]: datetime.date(2012, 2, 20)

So, the date is affected by the current time zone. There isn't
anything surprising here, of course. However, this makes DateField
really dangerous to use in USE_TZ setting. See below for examples.

Note that whatever you do, if you are using last_edited =
DateField(auto_now=True) together with USE_TZ, some user will see
last_edited either in the future, or in the past. Generally, even if
you want just the date for edit time, you want to use DateTimeField
and show the date in user's current time zone for correct behavior.
Maybe worth a mention in the model field documentation? "Dont use
DateFields when using use_tz=True (except when you know what you are
doing)" would be the short form of it. The long form might give the
last_edited date as one example, maybe poll closing date as another
example. Poll closing date of course doesn't make sense in USE_TZ
setting.

Another question I have meant to ask is if 1.4 is too early to have
USE_TZ = True as default setting? I am afraid there are still some
bugs to iron out, some documentation to improve, helper functions to
add and most of all the timezone handling might confuse new users.
Don't get me wrong: the feature is important and I like it. I just
wonder if the feature is polished enough at the moment. I think it was
actually me who gave the "include it on by default on settings
template" idea. So, I am not opposing that, just wondering if 1.4 is
too early.

An example from the tutorial, part 1:
def was_published_today(self):
return self.pub_date.date() == datetime.date.today()

This returns if the pub_date's date in UTC is the same date as today
in server's current time zone. This is not what the user wants. There
is no mention of USE_TZ in the tutorial. The server's time zone should
be set to UTC when USE_TZ is True. That would make
datetime.date.today() a lot safer, as it would compare correctly to
the UTC dates.

- Anssi

Aymeric Augustin

unread,
Feb 20, 2012, 3:59:18 PM2/20/12
to django-d...@googlegroups.com
(subject changed because I'm forking the discussion)

On 20 févr. 2012, at 21:29, Anssi Kääriäinen wrote:

> Another question I have meant to ask is if 1.4 is too early to have
> USE_TZ = True as default setting? I am afraid there are still some
> bugs to iron out, some documentation to improve, helper functions to
> add and most of all the timezone handling might confuse new users.

I was thinking about that too.

The main reason for enabling time zone support by default in new projects (through the settings.py template) was to store UTC in the database (on SQLite, MySQL and Oracle; PostgreSQL always does that anyway).

This decision was certainly skewed by my background in enterprise software, where reliable handling of datetimes is a no brainer. But this isn't the most common use case for Django.

Python doesn't make it very easy to deal with time zones, so forcing that concept on developers isn't friendly. The "right way" to do things is impractical, and there isn't that much space for improvement. Besides, the average website doesn't need time zone support, and IRC discussions show that developers don't care.

What do others think?

--
Aymeric.

Carl Meyer

unread,
Feb 20, 2012, 4:24:20 PM2/20/12
to django-d...@googlegroups.com
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 02/20/2012 01:59 PM, Aymeric Augustin wrote:
> The main reason for enabling time zone support by default in new
> projects (through the settings.py template) was to store UTC in the
> database (on SQLite, MySQL and Oracle; PostgreSQL always does that
> anyway).
>
> This decision was certainly skewed by my background in enterprise
> software, where reliable handling of datetimes is a no brainer. But
> this isn't the most common use case for Django.
>
> Python doesn't make it very easy to deal with time zones, so forcing
> that concept on developers isn't friendly. The "right way" to do
> things is impractical, and there isn't that much space for
> improvement.

Can you give more specifics here? Exactly how much harder is it to work
with USE_TZ = True than USE_TZ = False for a new Django developer,
presuming they don't really care about timezones at this point and just
want to do things more or less right so as not to box themselves in a
corner if they want to add real timezone support in the future?

I guess I think there's some value in setting people on the right path
earlier rather than later, but it really depends on exactly how much
harder that path is.

Carl
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk9CugQACgkQ8W4rlRKtE2fr6wCg2/cXMn/bHL/p6Cg5YDzZmPNe
AasAoKWeKEnDnWvcuYZR3EsqRsMlRfnB
=Sjc9
-----END PGP SIGNATURE-----

Donald Stufft

unread,
Feb 20, 2012, 4:17:49 PM2/20/12
to django-d...@googlegroups.com
I'm very much pro USE_TZ = True being the default. (On another note, i'm also Pro TIME_ZONE defaulting to UTC). UTC is the only time representation that makes sense for long term storage. All of the other timezones all have a long list of "gotchas" to dealing with them, especially
in the storage side.
--
Aymeric.

--
You received this message because you are subscribed to the Google Groups "Django developers" group.
To post to this group, send email to django-d...@googlegroups.com.
To unsubscribe from this group, send email to django-develop...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.

Danny Adair

unread,
Feb 20, 2012, 4:18:06 PM2/20/12
to django-d...@googlegroups.com
On Tue, Feb 21, 2012 at 09:29, Anssi Kääriäinen <anssi.ka...@thl.fi> wrote:
>[...]

>> This is by design. Timezones don't make sense for date or times, only for datetimes.
>
> In [15]: activate('Australia/Sydney')
> In [16]: localtime(now()).date()
> Out[16]: datetime.date(2012, 2, 21)
> In [17]: activate('Europe/Helsinki')
> In [18]: localtime(now()).date()
> Out[18]: datetime.date(2012, 2, 20)
>
> So, the date is affected by the current time zone.

You weren't handling date objects, just asking datetimes for their date.
As you said, nothing surprising here, but I don't understand how this
is "dangerous":

> DateField(auto_now=True) together with USE_TZ, some user will see
> last_edited either in the future, or in the past.

Timezone-aware that's what I would expect.
Using your above example, if I'm in Sydney saving a model instance,
the date will be 21 Feb. No timezone in it.
What else would you want to express with "auto_now" - if you have two
users in different timezones, whose date is the "authoritative" one?

Cheers,
Danny

Donald Stufft

unread,
Feb 20, 2012, 4:24:05 PM2/20/12
to django-d...@googlegroups.com
On Monday, February 20, 2012 at 4:24 PM, Carl Meyer wrote:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 02/20/2012 01:59 PM, Aymeric Augustin wrote:
The main reason for enabling time zone support by default in new
projects (through the settings.py template) was to store UTC in the
database (on SQLite, MySQL and Oracle; PostgreSQL always does that
anyway).

This decision was certainly skewed by my background in enterprise
software, where reliable handling of datetimes is a no brainer. But
this isn't the most common use case for Django.

Python doesn't make it very easy to deal with time zones, so forcing
that concept on developers isn't friendly. The "right way" to do
things is impractical, and there isn't that much space for
improvement.

Can you give more specifics here? Exactly how much harder is it to work
with USE_TZ = True than USE_TZ = False for a new Django developer,
presuming they don't really care about timezones at this point and just
want to do things more or less right so as not to box themselves in a
corner if they want to add real timezone support in the future?
In my experience with using Django 1.4a1, and now 1.4b1 with USE_TZ=True it has not been difficult. The biggest hurdle is that when generating
a date/time programmatically you need to make sure to attach a timezone to it. With pytz this is pretty easy. ``datetime.datetime().replace(<PYTZ Timezone>)`` instead of just ``datetime.datetime()``.

Really the biggest hurdle I had in using 1.4 with USE_TZ = True is that libraries I don't control tend to use date/times without a timezone attached causing an exception. I would argue that this is a benefit rather than a negative though as otherwise you just kind of assume that those other libraries are using the same timezone as you (``datetime.datetime.now vs date time.datetime.utcnow vs datetime's coming from another source in any other timezone``). And I feel like my code has less of a chance for silent data corruption now that I am no longer just assuming that libraries are using the same timezone as me and I explicitly attach a timezones to the incoming date/times asap.

I guess I think there's some value in setting people on the right path
earlier rather than later, but it really depends on exactly how much
harder that path is.

Carl
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk9CugQACgkQ8W4rlRKtE2fr6wCg2/cXMn/bHL/p6Cg5YDzZmPNe
AasAoKWeKEnDnWvcuYZR3EsqRsMlRfnB
=Sjc9
-----END PGP SIGNATURE-----

Anssi Kääriäinen

unread,
Feb 20, 2012, 4:28:39 PM2/20/12
to Django developers
On Feb 20, 10:59 pm, Aymeric Augustin
While I do not fall in the others category...

I quickly grepped the source code for datetime. I think there are at
least 30 lines (out of total 300) in the documentation which use
datetime incorrectly. Likely more. I think the code isn't totally safe
either. I don't think there is any way all of these can be fixed in
time for 1.4. Of course, punting 1.4 further back is another option.
In addition, database aggregation for example seems to be pretty hard
to do correctly (group by date etc).

For 1.5 I suggest a new module is added: django.utils.datetime. If
USE_TZ is True, then it returns all the times (if at all possible) in
UTC-aware datetime (actually datetime subclass instances). These
datetimes would have at least one additional method: .as_localtime().
If USE_TZ is False, it is the same as Python's datetime module (maybe
have localtime even in this case, it just returns self). That would
make fixing the code and documentation much easier, just use from
django.utils import datetime where you had used import datetime
before. Search & Replace mostly. Supporting the module might be a
little annoying, although datetime isn't exactly a fast-moving target
(one "new in version 2.x" for each of 5, 6, 7), and most of the
methods do not need overriding anyways.

- Anssi

Anssi Kääriäinen

unread,
Feb 20, 2012, 4:48:08 PM2/20/12
to Django developers
On Feb 20, 11:18 pm, Danny Adair <danny.ad...@unfold.co.nz> wrote:
> On Tue, Feb 21, 2012 at 09:29, Anssi Kääriäinen <anssi.kaariai...@thl.fi> wrote:
> >[...]
> >> This is by design. Timezones don't make sense for date or times, only for datetimes.
>
> > In [15]: activate('Australia/Sydney')
> > In [16]: localtime(now()).date()
> > Out[16]: datetime.date(2012, 2, 21)
> > In [17]: activate('Europe/Helsinki')
> > In [18]: localtime(now()).date()
> > Out[18]: datetime.date(2012, 2, 20)
>
> > So, the date is affected by the current time zone.
>
> You weren't handling date objects, just asking datetimes for their date.
> As you said, nothing surprising here, but I don't understand how this
> is "dangerous":

The danger is that a naive user will use DateField for last_edited
with auto_now=True. He really doesn't want that. The danger is that
the user might read the current tutorial and get his date handling
wrong. Of course the DateField isn't dangerous when you know what you
are doing. I don't think you can expect that from all the new users.
Current documentation doesn't help here.

> > DateField(auto_now=True) together with USE_TZ, some user will see
> > last_edited either in the future, or in the past.
>
> Timezone-aware that's what I would expect.
> Using your above example, if I'm in Sydney saving a model instance,
> the date will be 21 Feb. No timezone in it.
> What else would you want to express with "auto_now" - if you have two
> users in different timezones, whose date is the "authoritative" one?

I am fine with that. UTC date is actually the only way it can work
reasonably, as otherwise comparisons in the DB do not work sanely. The
auto_now code doesn't currently save the date in UTC time, it saves
date as in the user's time zone. The user likely doesn't realize that
using DateField for last edited date isn't wise. He wants
DateTimeField, even if he wants to show just the date part of it. That
works as expected, but Django's documentation doesn't currently
mention anything about that, at least not in DateField documentation.

Another danger is that in current Django trunk datetime.date.today()
doesn't return the UTC date, it returns the date in servers time zone
which is not UTC. This causes problems when comparing dates. This is
done in the tutorial which isn't updated to reflect the default USE_TZ
= True setting.

I feel pretty strongly that if USE_TZ = True, then the process' time
zone should be set to UTC. No expections. I don't think that is done
currently.

There are just too many items to polish if 1.4 is going to be released
anytime soon.

- Anssi

Jacob Kaplan-Moss

unread,
Feb 20, 2012, 5:52:56 PM2/20/12
to django-d...@googlegroups.com
Donald Stufft wrote:
> I'm very much pro USE_TZ = True being the default.

I very much agree.

I've been bitten by a few "can't use naive datetimes" errors as I've
been upgrading, but these are easy bugs: they show up when running
tests, and are fixed trivially.

On the other hand, the kind of bugs that *not* having good timezone
support causes are *much* more complicated: email notifications going
out at the wrong time, people's credit cards getting billed early or
late or not at all, etc. And don't get me started on calendaring.
Essentially, without timezones any sort of scheduling functionality is a
rats nest of subtle bugs. Adding timezone support exposes these bugs
early, and that's a *good thing*.

I think of it along the lines of Python 3's new Unicode support: it's a
bit of a pain as you learn the new rules, but once you learn them all
those run-time "cannot decode/encode" errors go away. Ditto timezones.

So yeah, USE_TZ=True in the default project template.

But I do think we should have some help for people transitioning --
perhaps a timezone FAQ would be in order?

Jacob

Danny Adair

unread,
Feb 20, 2012, 6:53:53 PM2/20/12
to django-d...@googlegroups.com
On Tue, Feb 21, 2012 at 10:48, Anssi Kääriäinen <anssi.ka...@thl.fi> wrote:
>[...]
> Current documentation doesn't help here.

I agree that a "Timezones FAQ" should mention
DateField(auto_now=True), with a reference from there also back to the
FAQ.

Really the complication are the timezones themselves, not the
mechanism handling them. If USE_TZ is True by default, users without
timezone experience should be advised that "today" can also be a
matter of location.

Cheers,
Danny

Yo-Yo Ma

unread,
Feb 20, 2012, 7:17:09 PM2/20/12
to Django developers
I haven't quite read up on all the UTC-related stuff in Django as of
yet (couldn't find much info about it), but I found some of the posts
above concerning. It would seem that if a DateTimeField should be
updated with ``timezone.now()``, then a DateField should be updated
with ``timezone.now().today()``, and TimeField should be updated with
``timezone.now().time()``, no? If I'm in EST time, and the server is
in MST, and it's 11:00PM on the server, my records should be updated
as the following day, since it's 1:00AM EST. Is this naive to assume
(if not, apologies for my lack of know-how regarding TZ issues)?

Danny Adair

unread,
Feb 20, 2012, 7:33:23 PM2/20/12
to django-d...@googlegroups.com

There's a logic to either way, but I agree that auto_now for a date
should use the user's timezone to determine "today", not the server's.
It would be very weird for me to add a model instance and be told that
I did that "tomorrow".

Cheers,
Danny

>
> --
> You received this message because you are subscribed to the Google Groups "Django developers" group.
> To post to this group, send email to django-d...@googlegroups.com.
> To unsubscribe from this group, send email to django-develop...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
>

--
Kind regards,

Danny W. Adair
Director
Unfold Limited
New Zealand

Talk:       +64 - 9 - 9555 101
Fax:        +64 - 9 - 9555 111
Write:      danny...@unfold.co.nz
Browse:     www.unfold.co.nz
Visit/Post: 253 Paihia Road, RD 2, Kawakawa 0282, New Zealand

"We are what we repeatedly do. Excellence, then, is not an act but a habit."

==============================
Caution
The contents of this email and any attachments contain information
which is CONFIDENTIAL to the recipient. If you are not the intended
recipient, you must not read, use, distribute, copy or retain this
email or its attachments. If you have received this email in error,
please notify us immediately by return email or collect telephone call
and delete this email.  Thank you.  We do not accept any
responsibility for any changes made to this email or any attachment
after transmission from us.
==============================

Yo-Yo Ma

unread,
Feb 20, 2012, 8:17:37 PM2/20/12
to Django developers
I actually know so little that I was even more confused by my own
question, but I appreciate your reply, Danny. I feel pretty challenged
when I try to understand timezone-related stuff. Is this correct:

When using UTC, which, if any, are true:

A) If I have a view that simply adds a record of a model with a
datetime field, and 3 users in different timezones load the view at
the same time, all 3 records will have the same datetime value
(assuming, of course, the database was able to write all 3 records
within the same microsecond)
B) UTC is *the* way to go for almost any application which will have a
timezone = models.CharField(... setting for each user profile
C) When each user has a timezone setting, it doesn't affect the
datetime that's entered into the database, it just gives me the
ability to display the time to them in their timezone

Danny Adair

unread,
Feb 20, 2012, 8:43:46 PM2/20/12
to django-d...@googlegroups.com
On Tue, Feb 21, 2012 at 14:17, Yo-Yo Ma <baxters...@gmail.com> wrote:
>[...]

> When using UTC, which, if any, are true:

Not sure what you mean by "using UTC", I assume you mean "USE_TZ = True".
As per first sentence of
https://docs.djangoproject.com/en/dev/topics/i18n/timezones/
"When support for time zones is enabled, Django stores date and time
information in UTC in the database, uses time zone-aware datetime
objects internally, and translates them to the end user’s time zone in
templates and forms."

> A) If I have a view that simply adds a record of a model with a
> datetime field, and 3 users in different timezones load the view at
> the same time, all 3 records will have the same datetime value
> (assuming, of course, the database was able to write all 3 records
> within the same microsecond)

They will have the same value in the database, yes.

> B) UTC is *the* way to go for almost any application which will have a
> timezone = models.CharField(... setting for each user profile

See above - database will store everything in UTC.
You could use a timezone field like that to store user timezone and
activate it, e.g. through a middleware -
https://docs.djangoproject.com/en/dev/topics/i18n/timezones/#selecting-the-current-time-zone

NB: PostgrSQL already stores UTC internally -
https://docs.djangoproject.com/en/dev/topics/i18n/timezones/#postgresql
"The PostgreSQL backend stores datetimes as timestamp with time zone.
In practice, this means it converts datetimes from the connection's
time zone to UTC on storage, and from UTC to the connection's time
zone on retrieval."
For other backends that store naive datetimes "in UTC" means "assumed
as being UTC".

> C) When each user has a timezone setting, it doesn't affect the
> datetime that's entered into the database, it just gives me the
> ability to display the time to them in their timezone

It doesn't affect the database.
But it's up to you (middleware) to "activate" their timezone in order
to make it the "current" timezone.
If you don't do that, the "default" timezone (TIME_ZONE setting) will
be the current timezone.
Whatever a user enters in their "current" timezone is converted to UTC
for storage - UTC is the only sane "common denominator".

Cheers,
Danny

Yo-Yo Ma

unread,
Feb 20, 2012, 9:53:14 PM2/20/12
to Django developers
Thanks, Danny. That's really helpful to me, and I appreciate you
taking the time to explain it.

Aymeric Augustin

unread,
Feb 21, 2012, 2:47:11 AM2/21/12
to django-d...@googlegroups.com
On 20 févr. 2012, at 23:52, Jacob Kaplan-Moss wrote:

> But I do think we should have some help for people transitioning --
> perhaps a timezone FAQ would be in order?

Jacob,

That's a good idea. I've created a ticket: https://code.djangoproject.com/ticket/17738

Everyone,

If you think timezones are hard, please post your questions or problems in the comments of that ticket, so I can address them in the FAQ.

Thanks!

--
Aymeric.

Anssi Kääriäinen

unread,
Feb 21, 2012, 2:49:54 AM2/21/12
to Django developers
On Feb 20, 11:24 pm, Carl Meyer <c...@oddbird.net> wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> On 02/20/2012 01:59 PM, Aymeric Augustin wrote:
>
> > The main reason for enabling time zone support by default in new
> > projects (through the settings.py template) was to store UTC in the
> > database (on SQLite, MySQL and Oracle; PostgreSQL always does that
> > anyway).
>
> > This decision was certainly skewed by my background in enterprise
> > software, where reliable handling of datetimes is a no brainer. But
> > this isn't the most common use case for Django.
>
> > Python doesn't make it very easy to deal with time zones, so forcing
> > that concept on developers isn't friendly. The "right way" to do
> > things is impractical, and there isn't that much space for
> > improvement.
>
> Can you give more specifics here? Exactly how much harder is it to work
> with USE_TZ = True than USE_TZ = False for a new Django developer,
> presuming they don't really care about timezones at this point and just
> want to do things more or less right so as not to box themselves in a
> corner if they want to add real timezone support in the future?
>
> I guess I think there's some value in setting people on the right path
> earlier rather than later, but it really depends on exactly how much
> harder that path is.

Some information about how hard this is can be gotten by updating the
tutorial part I to correctly use timezone aware datetimes. The
tutorial has actually the two most important problems in it:
- How do I get a timezone aware datetime? This should be explained
shortly in the tutorial, and link to further documentation.
- How do I correctly compare dates in timezone aware setting? This
should say that timezone affects what date it is. Here is how you
compare correctly dates in timezone aware way. (The comparison should
be localtime(self.pub_date).date() == localtime(now()).date()). I
think a small warning about DateFields would be good here.

Now, when you get how the timezone system in Django works it isn't
really that hard to do. My point is mainly that the documentation
currently doesn't actually work with USE_TZ = True, and there is some
work in updating it.

- Anssi

Anssi Kääriäinen

unread,
Feb 21, 2012, 3:00:21 AM2/21/12
to Django developers
On Feb 21, 2:33 am, Danny Adair <danny.ad...@unfold.co.nz> wrote:
> On Tue, Feb 21, 2012 at 13:17, Yo-Yo Ma <baxterstock...@gmail.com> wrote:
> > I haven't quite read up on all the UTC-related stuff in Django as of
> > yet (couldn't find much info about it), but I found some of the posts
> > above concerning. It would seem that if a DateTimeField should be
> > updated with ``timezone.now()``, then a DateField should be updated
> > with ``timezone.now().today()``, and TimeField should be updated with
> > ``timezone.now().time()``, no? If I'm in EST time, and the server is
> > in MST, and it's 11:00PM on the server, my records should be updated
> > as the following day, since it's 1:00AM EST. Is this naive to assume
> > (if not, apologies for my lack of know-how regarding TZ issues)?
>
> There's a logic to either way, but I agree that auto_now for a date
> should use the user's timezone to determine "today", not the server's.
> It would be very weird for me to add a model instance and be told that
> I did that "tomorrow".

The real problem is, as said before, that whatever you do, last edited
date doesn't work in multi-timezone setting. Somebody is going to see
last edited "tomorrow" or seeing his last edit as "yesterday".

I really, really think the date should be UTC date. That is what you
are going to do comparisons against in the DB. In other words, once
you put the date value into the DB, it will be in time zone UTC in
there when you compare it against any datetime value!

In addition, I will once more say that if settings.USE_TZ = True, then
the Python process default time zone should be UTC. When using time
zone aware datetimes, they are handled as UTC datetimes in the Python
process. I can't see any point why the time zone for the process
should be something else? What is gained by that? Isn't using Europe/
Helsinki for the process timezone downright dangerous due to daylight
saving times? Am I missing something obvious here?

- Anssi

Danny Adair

unread,
Feb 21, 2012, 3:57:34 AM2/21/12
to django-d...@googlegroups.com
On Tue, Feb 21, 2012 at 21:00, Anssi Kääriäinen <anssi.ka...@thl.fi> wrote:
>[...]
> The real problem is, as said before, that whatever you do, last edited
> date doesn't work in multi-timezone setting. Somebody is going to see
> last edited "tomorrow" or seeing his last edit as "yesterday".

I agree, "last edited" as a date with auto_now=True is useless.
Can you think of an example that's not? I haven't been able to yet.

> I really, really think the date should be UTC date. That is what you
> are going to do comparisons against in the DB. In other words, once
> you put the date value into the DB, it will be in time zone UTC in
> there when you compare it against any datetime value!

That goes together with your comment below about the default timezone
always being UTC.
If I'm in Sydney and the server's TIME_ZONE is Helsinki, either choice
will be converted.
The question was if TIME_ZONE is not UTC then whose "today" should it
be? And in that case I just find the user's "today" more logical than
the server's.
But again, this is only a problem for an "auto_now" date which I can't
think of a sensible use case for.

> In addition, I will once more say that if settings.USE_TZ = True, then
> the Python process default time zone should be UTC. When using time

Sorry I more or less just joined the discussion - I assume you mean by
that TIME_ZONE should not be configurable if USE_TZ is True, but
rather be fixed to UTC.

> zone aware datetimes, they are handled as UTC datetimes in the Python
> process. I can't see any point why the time zone for the process
> should be something else? What is gained by that? Isn't using Europe/
> Helsinki for the process timezone downright dangerous due to daylight
> saving times? Am I missing something obvious here?

What is gained by that is that there's a default "activation" in case
you don't provide one of your own.
At least that's what I understood the interna to do (always work with
UTC, convert to localtime for output, default to TIME_ZONE)
If that's not the case, I agree, "working" with a local time is very dangerous.
Nice example at http://pytz.sourceforge.net/#problems-with-localtime

I would personally prefer if timezone was part of auth.User,
activation built-in and always done, and TIME_ZONE always UTC.
Aymeric's response was:
"As long as Django doesn't have a schema alteration API, it's
difficult to change the User model.

There's also the question of how to store timezones in the database.
If we implemented this feature, we'd have to bless a timezone
implementation. pytz is pretty much the standard, and it's highly
recommended, but it's possible to use another implementation of tzinfo
classes if you desire."

which makes sense to me.

Cheers,
Danny

Aymeric Augustin

unread,
Feb 21, 2012, 4:05:16 AM2/21/12
to django-d...@googlegroups.com
On 21 févr. 2012, at 08:49, Anssi Kääriäinen wrote:

> Some information about how hard this is can be gotten by updating the
> tutorial part I to correctly use timezone aware datetimes.

This is a good point and I will ensure that the tutorial works properly (there's a ticket about that).

However, the tutorial isn't entirely representative. It often uses hardcoded values, which hardly ever happen in real code, for instance:

> >>> p.pub_date = datetime.datetime(2007, 4, 1, 0, 0)
> >>> p.save()


Best regards,

--
Aymeric.

Anssi Kääriäinen

unread,
Feb 21, 2012, 4:49:01 AM2/21/12
to Django developers
On Feb 21, 10:57 am, Danny Adair <danny.ad...@unfold.co.nz> wrote:
> The question was if TIME_ZONE is not UTC then whose "today" should it
> be? And in that case I just find the user's "today" more logical than
> the server's.

My point is that it should always be UTC. When you insert a date into
the database, it will appear to be UTC:
> select * from test_dates;
2012-02-21
> set time zone 'GMT-11';
> select * from test_dates where now() > datecol;
2012-02-21
> set time zone 'GMT+11';
> select * from test_dates where now() > datecol;
(0 rows)

Now, the connection time zone is always set to UTC (at least when
using PostgreSQL) so it would be consistent to get the last edited
date as UTC, too.

The main point is this: when you store a date into the database you
lose the information about in whose time zone the date was. You store
the last_edit date as a date in Sydney time, but in the DB there is no
information that it is in Sydney time. So, it is better to store it in
UTC time to begin with.

However there are no right answers here. It is better to avoid
DateFields completely for last edited or poll closes type stuff when
USE_TZ is True. If you are going to compare datetimes and dates, the
correct answer depends on the user's time zone. In some cases you want
the date in UTC time. Poll closes at one point in time, you don't want
to have the poll open for some users because they happen to be in a
"late" time zone. In some cases you want the date in local time zone
(last edited date depends on user's time zone). That is why DateFields
are in my opinion dangerous in USE_TZ setting. The documentation
should warn about this.

Of course, if you are using USE_TZ = True just to get internal
handling in UTC, but you are only using just one time zone, then your
viewpoint will be different. I am talking about true multi-timezone
applications here.

> > zone aware datetimes, they are handled as UTC datetimes in the Python
> > process. I can't see any point why the time zone for the process
> > should be something else? What is gained by that? Isn't using Europe/
> > Helsinki for the process timezone downright dangerous due to daylight
> > saving times? Am I missing something obvious here?
>
> What is gained by that is that there's a default "activation" in case
> you don't provide one of your own.
> At least that's what I understood the interna to do (always work with
> UTC, convert to localtime for output, default to TIME_ZONE)
> If that's not the case, I agree, "working" with a local time is very dangerous.
> Nice example athttp://pytz.sourceforge.net/#problems-with-localtime

I am not talking about the default time zone for users. I am talking
about the default time zone of the Python process. What is stored in
os.environ['TZ']. As you can have only a single value there (changing
it in-flight is a no-no due to threading issues) I think the sanest
choice is to have it as UTC. Sorry for the confusion about this.

- Anssi

Aymeric Augustin

unread,
Feb 21, 2012, 5:02:14 AM2/21/12
to django-d...@googlegroups.com
On 21 févr. 2012, at 10:49, Anssi Kääriäinen wrote:

>>> I can't see any point why the time zone for the process
>>> should be something else? What is gained by that? Isn't using Europe/
>>> Helsinki for the process timezone downright dangerous due to daylight
>>> saving times? Am I missing something obvious here?
>>
>> What is gained by that is that there's a default "activation" in case
>> you don't provide one of your own.
>> At least that's what I understood the interna to do (always work with
>> UTC, convert to localtime for output, default to TIME_ZONE)
>> If that's not the case, I agree, "working" with a local time is very dangerous.
>> Nice example athttp://pytz.sourceforge.net/#problems-with-localtime
>
> I am not talking about the default time zone for users. I am talking
> about the default time zone of the Python process. What is stored in
> os.environ['TZ']. As you can have only a single value there (changing
> it in-flight is a no-no due to threading issues) I think the sanest
> choice is to have it as UTC. Sorry for the confusion about this.

os.environ['TZ'] controls the ouptut of functions such as datetime.fromtimestamp().

If you're running with USE_TZ = True, you should use the UTC versions, e.g. datetime.utcfromtimestamp() in your own code. However, you may be relying on third party code that hasn't been adapted for time zone support yet.

For such code to work properly, it's better to keep settings.TIME_ZONE == os.environ['TZ'] == your "main" time zone == what the user sees by default.

Best regards,

--
Aymeric.

Anssi Kääriäinen

unread,
Feb 21, 2012, 5:32:45 AM2/21/12
to Django developers
On Feb 21, 12:02 pm, Aymeric Augustin
<aymeric.augus...@polytechnique.org> wrote:
> os.environ['TZ'] controls the ouptut of functions such as datetime.fromtimestamp().
>
> If you're running with USE_TZ = True, you should use the UTC versions, e.g. datetime.utcfromtimestamp() in your own code. However, you may be relying on third party code that hasn't been adapted for time zone support yet.
>
> For such code to work properly, it's better to keep settings.TIME_ZONE == os.environ['TZ'] == your "main" time zone == what the user sees by default.

I guess this is true. Maybe this is about different viewpoints about
having true multi-timezone applications, where having UTC as default
would make sense. More to the point: in true multi-timezone setting
any default time zone for output will be incorrect, so UTC makes as
much sense as any. Then again, you can just configure it to that.

I have been thinking this from the viewpoint of the developer. For the
developer seeing non-aware datetimes in UTC would probably make more
sense than seeing them in local timezone. I guess logging is going to
be using the os.environ['TZ'] time zone for example. However, this is
the developer viewpoint. I agree getting correct displayed value for
the user is more important.

- Anssi
Reply all
Reply to author
Forward
0 new messages