Exactly!
There seems to be the assumption in other messages in this thread that
Django 'owns' the database. That is not the philosophy Django takes - it
interfaces with the DB. In some cases, Django 'owns' the data and would
have the liberty of choosing/changing the format e.g. in tables provided
by contrib apps, such as the session data which stores pickled Python
objects, or the format of the password in the auth.User table. But
globally changing the format of how datetimes are stored in SQLite is
just not an option (at least not until Django 2.0), unless we can
guarantee backwards compatibility with existing data and other apps use
of the data.
Regards,
Luke
--
"We may not return the affection of those who like us, but we
always respect their good judgement." -- Libbie Fudim
Luke Plant || http://lukeplant.me.uk/
> Django actually already adds support for some capabilities to certain
> database backends, if I'm not mistaken - such as cascades through GFKs
> on delete.
>
> In terms of time zones, could django "assume"/ensure that the datetime
> stored in the backend is UTC, then handle the conversion to the local
> timezone itself?
Isn't this a viable solution? It's the universal, cross-timezone-friendly datetime objects that we care about, not the timezones they were in, right?
- If the DB supports timezone-aware datetime fields, just pass the datetime object through as is.
- If the DB doesn't support timezone-aware datetime fields, convert to UTC and store the datetime as UTC
- If the datetime has tz info, convert the time to UTC using that
- If the datetime doesn't have tz info, convert using the default timezone specified in the settings
When retrieving the data from a non-timezone-aware db, convert them from UTC to the project's timezone.
Sam
For cases where you do want to retain the timezone, how about allowing the TZ-aware DateTime field to store the TZ data to an optional secondary field? That field could be a regular CharField. It wouldn't be needed for any of the date-based sorting or filtering. There's precedent for this sort of behaviour with the GenericForeignKey, and I think it would be fine, especially if the secondary field was optional.
What do you think?
Sam
> --
> 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.
>
This seems like probably the correct solution to me. I'd like to suggest that the time itself still be stored in UTC so that reading the timezone field is (somewhat) optional
> Storing the TZ in a separate field is going to get pretty nasty for
> sorting as well, as the query will have to somehow concatenate or
> compute together the two fields before applying the sorting algorithm.
I don't see why. If the datetime data is all normalized to UTC then the datetime column can be used for sorting on its own and the tz data can be ignored.
> I think the best way to handle multi-TZ timestamps is the way that
> Unix and other multi-user, multi-timezone OSes have been doing it for
> decades (mostly wrt to filesystems) - respect the TZ of the client
> inputting the data, normalize to a common TZ (usually UTC) and store
> as such. Perform all sorting and timestamp comparison/arithmetic in
> that single, normalized TZ. Upon output, render the value in the
> client's TZ.
>
> ...and that is essentially what Postgres does.
I think we agree here. I'm suggesting the separate tz field as a nice-to-have. I think Django has everything it needs to make DateTimeField timezone-aware. It sounds like its already doing the right thing with postgresql. It just needs a graceful fallback for other DBs that don't do timezones as well.
Here's my proposal for adding timezone support to DateTimeField:
1. Assume timezone-less datetimes are in the timezone specified in settings and convert them to timezone-aware datetimes
2. If the db bridge doesn't understand timezone data, normalize the datetimes to UTC before sending them through
3. When retrieving datetimes from the db, assume they are in UTC if they don't come with a timezone already attached
4. Convert the datetimes to the timezone specified in settings
Bonus:
5. Allow the user to specify a field in the DateTimeField declaration to be used for storing timezone data
6. When storing, extract the timezone and record it in this field
7. When retrieving, convert the datetime from UTC to the timezone specified in the field
I could put together a patch for this solution if you folks think it looks promising.
Sam
That is a domain specific assertion, I don't believe that is true in
all cases. Typically, when we put things into the ORM, we expect to
get the same things out again. If you consider viewing a timeline of a
users activities, we might want to display the datetime of an event in
both the viewing users timezone and the viewees timezone. If that
information is discarded as irrelevant, then we could not do so.
I could certainly see what you are describing as a specific field - a
NormalizedDateTimeField, which explicitly normalizes to UTC for
storage and to settings.TZ for display - but it shouldn't be the only
way.
Cheers
Tom
Right, but this isn't DanielsWebFramework, we need to cover more than
what you find personally useful.
Maybe what I'm suggesting is incredibly esoteric, and should only
belong in TomsWebFramework, but I can definitely see the utility in a
DateTimeField that is TZ-aware and reconstitutes precisely the
TZ-aware datetime that was put into it - so not just the UTC offset,
but the specific TZ.
I'm aware that this isn't how databases handle this internally, this
is why we have an ORM, in order to be clever.
Cheers
Tom
> The main difference between MySQL's "timestamp" field type and
> PostgreSQL's "timestamp with time zone" field type (and indeed also
> MySQL's "datetime" field type) is the date range that they support.
> MySQL's "timestamp" field type is modeled on Unix epoch timestamps,
> and therefore does not support dates earlier than 1 Jan, 1970 00:00:00
> UTC. PostgreSQL's "timestamp with time zone" field type on the other
> hand is modeled on Julian dates, and supports dates ranging from 4713
> BC to 294276 AD (with 1 µs accuracy, I might add). And MySQL's
> "datetime" field type supports some bizarre range of
> '0000-00-00' (yes, you really can specify the zero'th day of the
> zero'th month... isn't that cool?) to '9999-12-31'. One can only hope
> that Oracle's acquisition of MySQL might one day lead to better SQL
> compliance.
Uh, no. 0000-00-00 is specifically an illegal value in MySQL. Invalid
dates are converted to 0000-00-00 unless you are in strict mode, in
which case they raise error conditions. The actual supported range is
from 1000-01-01 to 9999-12-31.
http://dev.mysql.com/doc/refman/5.0/en/datetime.html
--
Question the answers
On Jun 30, 11:06 am, Tom Evans <tevans...@googlemail.com> wrote:I personally find it relatively useless to know what the wall clock
> That is a domain specific assertion, I don't believe that is true in
> all cases. Typically, when we put things into the ORM, we expect to
> get the same things out again. If you consider viewing a timeline of a
> users activities, we might want to display the datetime of an event in
> both the viewing users timezone and the viewees timezone. If that
> information is discarded as irrelevant, then we could not do so.
time was when something happened in another timezone. I find it more
relevant to know what time it was for me, when said event occurred. In
most such cases, if the local time of the event was of importance,
then the *location* of the event would also be important, and probably
stored in the same DB model. If pytz is utilized, then we have a full
database of timezones at our disposal, and can derive from a location
what the local TZ was in that location at that particular moment in
time. More accurately, we can ascertain what the UTC offset was, and
whether DST was in effect - since those rules have changed through
history, and will continue to change.
Western Samoa for example, will move to the other side of the
international date line on December 29th this year, effectively
jumping from a UTC-11 offset to a UTC+11 offset (skipping an entire
day in the process). Whilst such events are rare, it illustrates that
it is more useful to store the location of an event, plus have access
to the Olson tzdata DB, than to simply store a -11 or +11 offset
(which does not indicate whether DST was in effect). "Pacific/Samoa"
on the other hand can be looked up in tzdata, which will have an entry
stating that from 4 July 1892 until 29 December 2011, Samoa's UTC
offset was -11, at which point it changes to +11.
For correct chronological sorting of events (which may occur in
multiple different timezones), or calculating deltas between
timestamps, life is a lot easier if you normalize to a common TZ, eg.
UTC, and only apply a local TZ offset when rendering the output to the
user.
Since 4.0 came out in the late 1990s, isn't is possible that things
have improved somewhat over your dozen year gap of ignorance?
(I'll stop feeding trolls now)
--
Question the answers
Strictly speaking, converting a naive datetime + a time zone to a "point in time" (eg. UTC timestamp) isn't possible, because of DST: one hour doesn't exist, and another one happens twice. In my opinion, the primary goal of the DateTime field is to store a "point in time" and it should do so unambiguously. Of course, we could store a naive datetime plus a time zone plus a DST flag, but that's cumbersome, I'd even say developer-hostile.
I think there's a consensus on the fact that the best representation for DateTime fields is UTC. I'm willing to trust the pytz guys on this topic:
> The preferred way of dealing with times is to always work in UTC, converting to localtime only when generating output to be read by humans.
Thus, Django should always use UTC internally and on the connection with the database, and convert to local time in the forms widgets and localization functions. However, this is massively backwards incompatible in all databases that store DateTime as naive objects in local time (all but PostgreSQL). As a consequence, it won't be considered (or maybe in Django 2.0 ?)
For the example given above, I agree that storing a date + a time would be more appropriate. We could introduce a new field that keeps track of the time zone the date was entered in, but that comes after fixing DateTime fields to use UTC.
Finally, it isn't impossible to work around this problem in Django 1.3. I'm currently working on an application where I need to track time intervals exactly, so I must to store datetimes in UTC. I have written LocalDateTime model and form fields that store DateTimes in UTC (with TIME_ZONE = 'utc') but display it in local time in forms and in the admin (according to a custom setting, LOCAL_TIME_ZONE = 'Europe/Paris'). This takes around 50 lines of code. I had to monkey-patch `localize` to do the conversion on display, but otherwise it's very simple. I just have to remember to use `LocalDateTime` instead of `models.DateTime`.
Of course, since the UI is in local time, an user can still enter an ambiguous datetime. That's unavoidable: an UI in UTC isn't acceptable for my end users, and neither is an "is_dst" checkbox. But all datetimes generated internally are correct, and that's the most important for me.
Best regards,
--
Aymeric Augustin.
I'm no expert on time zone handling, but shouldn't the two datetimes
already have two different timezones in that case? For example,
01:30:00 CDT, followed by 01:30:00 CST an hour later, if the user is
in the U.S. Central time zone. Both of those times should be
convertible to distinct UTC times. Likewise for the CST to CDT
transition in the spring.
Cheers,
Ian
On 30 juin 2011, at 19:06, Daniel Swarbrick wrote:Strictly speaking, converting a naive datetime + a time zone to a "point in time" (eg. UTC timestamp) isn't possible, because of DST: one hour doesn't exist, and another one happens twice.
> On Jun 30, 6:31 pm, Ian Clelland <clell...@gmail.com> wrote:
>
>> As a counterexample, I have needed to store wall-clock time as well as time
>> zones for future events, in scheduling applications. It is exactly because
>> of the unpredictability of future DST changes (and, in very rare cases,
>> wholesale time zone changes) that a one-time UTC conversion simply does not
>> work for timestamps in the future.
>>
>> When an event is scheduled for a specific time, on a specific date in the
>> future, then users expect that the web service will react at the appropriate
>> wall clock time. An unforseen change in daylight saving time legislation
>> should not have the effect of making the time in the database incorrect.
>
> That is a good example, which I agree with. Although it sounds like
> more of a case for storing the date and time as separate fields (which
> is already feasible), since Python dates and times on their own have
> no tzinfo struct... only the combined datetime does (whether or not it
> includes hours/mins/secs components).
In my opinion, the primary goal of the DateTime field is to store a "point in time" and it should do so unambiguously. Of course, we could store a naive datetime plus a time zone plus a DST flag, but that's cumbersome, I'd even say developer-hostile.
I think there's a consensus on the fact that the best representation for DateTime fields is UTC. I'm willing to trust the pytz guys on this topic:
> The preferred way of dealing with times is to always work in UTC, converting to localtime only when generating output to be read by humans.
Thus, Django should always use UTC internally and on the connection with the database, and convert to local time in the forms widgets and localization functions. However, this is massively backwards incompatible in all databases that store DateTime as naive objects in local time (all but PostgreSQL). As a consequence, it won't be considered (or maybe in Django 2.0 ?)
I doubt it was your intention, but this kind of argument can *so*
easily spiral into a flamewar. Certain things -- text editors,
monospace fonts, operating systems, database engines -- just can't be
successfully discussed. Luckily, they're also off-topic for this list,
so let's bring things back to the discussion at hand and steer clear
of religious territory, OK?
Jacob