我有一个django应用程序,它在数据库(postgres)中存储UTC的日期时间,它在全球范围内都有用户。
但是在应用程序逻辑中,我根据当地时间范围进行了一些验证,即用户在瓜亚基尔,有些事情在星期天发生;我有问题要执行它并进行一些调试我发现在UTC是星期一凌晨2点,但用户(美国/瓜亚基尔)UTC-5仍然在周日21:00。所以它对用户来说是失败的,因为DAY已经改变了。
我正在考虑将用户时区存储在用户表中,但我不知道如何设置它以及如何防止以前的情况。
作为一个附带问题,如何将存储在数据库中的UTC日期时间转换为用户(例如)电子邮件通知的时区。 (我不会给他发送一封日期时间和时区的电子邮件,让他在脑海里做数学计算。)
答案 0 :(得分:6)
这很好,你将所有内容存储在UTC
中。现在您不需要将用户时区存储在数据库中,您可以在登录页面上执行此操作,您可以计算UTC
的用户偏移量并存储在会话vi ajax中。以下是您可以在登录页面模板中包含的简单脚本:
<script>
$(document).ready(function(){
var visitortime = new Date();
var visitortimezone = - visitortime.getTimezoneOffset()/60;
$.ajax({
type: "POST",
url: "{% url 'update_timezone' %}",
data: {'time_zone': visitortimezone, 'csrfmiddlewaretoken': '{{csrf_token}}'},
dataType: "text"
});
});
</script>
在您的根urls.py中添加此网址:
url(r'^update_timezone/$',
'MySite.views.update_timezone',
name='update_timezone'),
添加此视图:
def update_timezone(request):
time_zone = request.POST.get('time_zone', 0)
if time_zone:
request.session['user_timezone_offset'] = float(time_zone)*60*60
return HttpResponse(
simplejson.dumps({}), mimetype='application/javascript')
现在,您在会话中拥有用户时区偏移量。现在是计算的部分。您需要这两个简单的辅助函数:
from datetime import timedelta
def add_user_offset(dt, offset):
if offset:
dt = dt + timedelta(seconds=offset)
return dt
def subtract_user_offset(dt, offset):
if offset:
dt = dt - timedelta(seconds=offset)
return dt
好的,如果您想根据他/她的时区显示用户时间,您可以这样做:
created = add_user_offset(obj.created, request.session.get('user_timezone_offset'))
如果您有来自表单的日期时间或日期,并且您想验证它,例如所选日期不应小于您当前的日期:
from django.utils import timezone
d = request.POST['date']
d_normalize = subtract_user_offset(d, request.session.get('user_timezone_offset'))
if d_normalize < timezone.now():
raise Exception, 'Date must be in future'
此方法的好处是您无需要求用户指定其时区。我们自动完成所有工作。
答案 1 :(得分:1)
django中的全局策略是在持久层中使用UTC,并在与最终用户交互时使用本地时间(您可以查看here。 因此,在您的用例中,我将在数据库中保留UTC时间并使用当前时区来处理您需要的计算。
时区选择功能为here 。使用get_current_timezone()可以获得tzinfo对象。
当前时区是用于呈现网页的时区。它可能不是您想要的那个,例如用户是否想要使用UTC-1时区但是当前正在看UTC + 1的网页。在这种情况下,最好以Aamir所解释的类似方法保持会话中的时区或保持它。
模型中持久化的方法仅仅是使用CharField并使用pytz包放置时区字符串。
答案 2 :(得分:-1)
默认django是美国/芝加哥时区。您需要将用户时区存储在数据库中以及用户登录时从DB获取时区并通过代码更改配置的最佳方式。
import datetime
from django.utils.timezone import utc
now = datetime.datetime.utcnow().replace(tzinfo=utc)
https://docs.djangoproject.com/en/dev/ref/settings/#time-zone