id,summary,reporter,owner,description,type,status,component,version,severity,resolution,keywords,cc,stage,has_patch,needs_docs,needs_tests,needs_better_patch,easy,ui_ux 14981,Small enhancement to User.last_login timezone handling (version 1.3.0 beta 1),jamercee,nobody,"Attached is a small patch to enhance the timezone handling of django.contrib.auth to ensure that the last_login and date_joined datetime fields are stored in UTC format. I recognize these patches make an assumption about timezone that may represent a breaking change. But after reviewing the source code, it would appear the User.last_login and User.date_joined fields were never intended to store timezone. Instead, they relied on timezone information provided by the underlying OS. This introduced the possibility for subtle development --> production system differences. For example, we have been performing development on Windows, and host our production code on FreeBSD 8.x. Under Windows, even with settings.TIME_ZONE='UTC', the returned value from is always localtime. But on FreeBSD it results in the correct UTC results. The difference meant that code intended to display User.last_login on Windows was different from the coded needed to display these same values on FreeBSD. This subtle difference created a more complex debug environment. The solution in the patch is to switch to only call datetime.datetime.utcnow() in the code. I should mention that prior to submitting the patch, we reviewed the possibility of rolling the functionality into user profiles, and also the possibility of solving the issue by trying to somehow intercept the signal of the login() event. But each of these approaches seemed to come up short to what was essentially a simple solution. We acknowledge this may not be the ""right"" way to solve this issue. But it seemed like we should start with submitting a patch, and allow the Django team to make the final decision. If you'd prefer to see a different approach to solving this in a more ""django appropriate"" way -- just let me know. We're new to the django world, but it's a fantatic system, and we'd be pleased to follow experienced guidance. ---- '''Code Sample:''' Once this patch is applied, converting from UTC to local-timezone is a trivial affair using pytz. Here's an example of how to display last_login from a session that has already been authenticated. {{{ from django.contrib import auth from django.http import HttpResponse from django.contrib.auth.decorators import login_required import pytz @login_required def show_last_login(request): ll_utc = pytz.utc.localize(request.user.last_login) ll_loc = ll_utc.astimezone(pytz.timezone(settings.TIME_ZONE)) html = ""last login {0}"".format(ll_loc) return HttpResponse(html) }}}",,closed,contrib.auth,1.3-alpha,,wontfix,TIME_ZONE last_login UTC,,Unreviewed,1,0,0,0,,