如何获取访问者的当前时区,然后将timezone.now()转换为Django 1.4中的本地时间字符串?

时间:2012-04-14 22:01:57

标签: python django timezone

据我所知,现在使用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变量的一部分),所以既然我是America/New_York,我假设Django可以找出每个访问者自己的本地时区(基于HTTP头)?

无论如何,所以我的问题是双重的:

  1. 如何在ajax.py中获取访问者的本地时区? (可能将其作为字符串参数传递,如{{ TIME_ZONE }}
  2. 使用访问者的本地时区,如何将UTC timezone.now()转换为本地时区,并使用Django dateformat输出为字符串?
  3. 对于@agf

    编辑

    timezone.now()给出了USE_TZ = True

    时的UTC时间
    # 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 =东部标准时间)吗?

3 个答案:

答案 0 :(得分:10)

您需要仔细阅读Django Timezones docs

一点很重要:

  

没有相当于Django可以用来自动确定用户时区的Accept-Language HTTP标头。

您必须询问用户他们的时区是什么,或者只是使用默认值。

您还需要确保:

USE_TZ = True

settings.py

获得时区tz后,您可以:

from django.utils import timezone

timezone.activate(tz)

datetime = timezone.now() if checked else None

在时区datetime中获取时区感知tz个对象。

答案 1 :(得分:6)

虽然浏览器不会向服务器发送指示时区的任何标头,但JavaScript环境 知道其当前时区。

这有两个重要的影响:当服务器无法在初始请求中找到您当前的时区时,您可以发送一些javascript代码,这将确定TZ偏移并将该信息发回到服务器,以便区域信息可以从那一点开始与当前会话相关联。

但更重要的是,如果您在JSON数据中发送时间值(将由浏览器客户端解释),则浏览器的时区不会需要。相反,您只需要确保JSON输出中存在时区偏移量,以便浏览器可以在事后进行自己的时区数学计算。

var now = new Date()
var offset_minutes = now.getTimezoneOffset()  # e.g. 240 for GMT-0400

答案 2 :(得分:1)

既然你想要用户'时区,我觉得这应该在浏览器上用Javascript完成。

我将这样的内容传递给模板:

{"t": str(obj.timestamp))

其中obj是django模型的一个实例,其中timestamp字段的类型为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>

对我来说,这会输出类似于:2017年2月15日,下午05:22:24(太平洋标准时间)

相关文件: