我知道现在使用 Django 1.4 的最佳实践是将所有datetime
都存储在 UTC 中,我同意这一点。我也明白所有时区对话都应该在模板级别完成,如下所示:
{% load tz %}
{% timezone "Europe/Paris" %}
Paris time: {{ value }}
{% endtimezone %}
但是,我需要在 Python 中将 UTC 时间转换为request
的本地时间。我无法使用模板标签,因为我使用 Ajax(更具体地说是 Dajaxice)在 JSON 中返回字符串。
目前这是我的代码ajax.py
:
# checked is from the checkbox's this.value (Javascript).
datetime = timezone.now() if checked else None
$ order_pk is sent to the Ajax function.
order = Order.objects.get(pk=order_pk)
order.time = datetime
order.save()
return simplejson.dumps({
'error': False,
'datetime': dateformat.format(datetime, 'F j, Y, P') if checked else 'None'
})
因此,即使当前时间以 EST 时间(我的本地时区)April 14, 2012, 5:52 p.m.
,JSON 响应也会返回 April 14, 2012, 9:52 p.m
,因为那是 UTC 时间。
我还注意到 Django 为每个请求存储一个名为 TIME_ZONE
的模板变量(实际上不是 request
变量的一部分),所以既然 my 是America/New_York
,我假设 Django 可以找出每个访问者自己的本地时区(基于 HTTP 标头)?
无论如何,所以我的问题是双重的:
- 如何在
ajax.py
中获取访问者的本地时区?(可能将其作为字符串参数传递,例如{{ TIME_ZONE }}
) - 使用访问者的本地时区,如何将 UTC
timezone.now()
转换为本地时区并使用 Django 的dateformat
输出为字符串?
编辑:为了@agf
timezone.now()
给出了 UTC 时间,当USE_TZ = True
:
# From django.utils.timezone
def now():
"""
Returns an aware or naive datetime.datetime, depending on settings.USE_TZ.
"""
if settings.USE_TZ:
# timeit shows that datetime.now(tz=utc) is 24% slower
return datetime.utcnow().replace(tzinfo=utc)
else:
return datetime.now()
有没有办法将datetime
转换为 UTC 以外的其他内容?例如,我可以做类似 current_time = timezone.now()
、然后current_time.replace(tzinfo=est)
(EST = 东部标准时间)之类的操作吗?
你需要仔细阅读 Django 时区文档。
重要的一点:
没有等效的接受语言HTTP头,Django可以用来自动确定用户的时区。
您必须询问用户他们的时区是什么,或者只是使用默认值。
您还需要确保:
USE_TZ = True
在你的settings.py
.
获得时区tz
后,您可以:
from django.utils import timezone
timezone.activate(tz)
datetime = timezone.now() if checked else None
获取时区感知datetime
对象 时区 tz
。
虽然浏览器不会向服务器发送任何指示时区的标头,但 JavaScript 环境确实知道其当前时区。
这有两个重要影响:虽然服务器无法在初始请求中找到您当前的时区,但您可以发送一些 javascript 代码来确定 TZ 偏移量并将该信息发送回服务器,以便区域信息可以从该点开始与当前会话相关联。
但更重要的是,如果您在 JSON 数据中发送时间值,这些数据将由浏览器客户端解释,则不需要知道浏览器的时区。相反,您只需确保 JSON 输出中存在时区偏移量,以便浏览器可以在事后执行自己的时区数学运算。
var now = new Date()
var offset_minutes = now.getTimezoneOffset() # e.g. 240 for GMT-0400
由于您想要用户的时区,因此这应该在使用 Javascript 的浏览器上完成对我来说是有意义的。
我将这样的东西传递到模板中:
{"t": str(obj.timestamp))
其中 obj 是 django 模型的一个实例,其中时间戳字段的类型为 DateTimeField。
模板:
<div class="timestring">{{ t }}</div>
...
<script>
$('.timestring').each(function(){
var d = new Date($(this).text());
$(this).text(d.toLocaleDateString() + ", " + d.toLocaleFormat("%r (%Z)"));
})
</script>
对我来说,这输出如下: 2/15/2017, 05:22:24 PM (PST)
相关文档:
Javascript Date 类(特别是接受日期字符串的构造函数和 toLocaleFormat() 方法)
strftime(带有许多日期格式快捷方式)