Python 如何获得访客';然后将timezone.now()转换为Django 1.4中的本地时间字符串?

Python 如何获得访客';然后将timezone.now()转换为Django 1.4中的本地时间字符串?,python,django,timezone,Python,Django,Timezone,我知道Django 1.4现在的最佳实践是在UTC中存储所有的datetime,我同意这一点。我还理解,所有时区对话都应该在模板级别进行,如下所示: {% load tz %} {% timezone "Europe/Paris" %} Paris time: {{ value }} {% endtimezone %} 但是,我需要将UTC时间转换为Python中的请求的本地时间。我不能使用模板标记,因为我使用Ajax(更具体地说)返回JSON中的字符串 目前这是我的代码ajax.p

我知道Django 1.4现在的最佳实践是在UTC中存储所有的
datetime
,我同意这一点。我还理解,所有时区对话都应该在模板级别进行,如下所示:

{% load tz %}

{% timezone "Europe/Paris" %}
    Paris time: {{ value }}
{% endtimezone %}
但是,我需要将UTC时间转换为Python中的
请求的本地时间。我不能使用模板标记,因为我使用Ajax(更具体地说)返回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'
})
因此,即使当前时间是东部时间(我的本地时区)2012年4月14日下午5:52,JSON响应也将返回2012年4月14日下午9:52,因为这是UTC时间

我还注意到Django为每个请求存储了一个名为
时区
的模板变量(实际上不是
请求
变量的一部分),因此由于我的是
美国/纽约
,我假设Django可以计算出每个访问者自己的本地时区(基于HTTP头)

总之,我的问题有两个:

  • 如何在我的
    ajax.py
    中获取访问者的本地时区?(可能作为字符串参数传递,如
    {{TIME_ZONE}}
  • 对于访问者的本地时区,如何将UTC
    时区.now()
    转换为本地时区,并使用Django的
    日期格式作为字符串输出
  • 编辑:用于@agf

    timezone.now()
    给出
    USE\u 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()
    
    是否需要将
    日期时间
    转换为UTC以外的其他格式?例如,我可以做一些类似于
    current\u time=timezone.now()
    ,然后
    current\u time.replace(tzinfo=est)
    (est=Eastern Standard time)的事情吗?

    您需要仔细阅读

    重要的一点是:

    Django无法使用与Accept Language HTTP头等效的方法自动确定用户的时区

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

    您还需要确保:

    USE_TZ = True
    
    在您的
    设置.py

    一旦您有了时区
    tz
    ,您就可以:

    from django.utils import timezone
    
    timezone.activate(tz)
    
    datetime = timezone.now() if checked else None
    

    要在timezone
    tz

    中获取时区感知的
    datetime
    对象,而浏览器不向服务器发送任何指示时区的标头,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))
    
    <div class="timestring">{{ t }}</div> 
    ...
    <script>
      $('.timestring').each(function(){
        var d = new Date($(this).text());
        $(this).text(d.toLocaleDateString() + ", " + d.toLocaleFormat("%r (%Z)"));
      })
    </script>
    
    其中obj是django模型的实例,其中时间戳字段的类型为DateTimeField

    模板:

    {"t": str(obj.timestamp))
    
    <div class="timestring">{{ t }}</div> 
    ...
    <script>
      $('.timestring').each(function(){
        var d = new Date($(this).text());
        $(this).text(d.toLocaleDateString() + ", " + d.toLocaleFormat("%r (%Z)"));
      })
    </script>
    
    {{t}
    ...
    $('.timestring')。每个(函数(){
    var d=新日期($(this).text());
    $(this).text(d.toLocaleDateString()+“,+d.toLocaleFormat(“%r(%Z)”);
    })
    
    对我来说,这输出类似于:2017年2月15日,下午5:22:24(太平洋标准时间)

    有关文件:

    • (请特别参阅接受日期字符串的构造函数和toLocaleFormat()方法)


    好的,我首先要做
    时区。现在()
    时区之前。激活(tz)
    并将其存储到
    顺序中,对吗?但是,如果您希望默认时区具有时区感知的datetime,那么将有两个不同的
    日期时间
    @hobbes3,然后是。如果您想要时区识别UTC datetime,而默认时区不是UTC,那么请使用。您需要转换为UTC。@hobbes3您可以始终使用
    somedatetime.replace(tz=sometz)
    。很抱歉,我刚刚意识到我的第一条评论非常含糊不清。我想说的是,我想首先用
    current\u time=timezone.now()
    ,将当前UTC时间附加到
    order
    (将其存储到数据库),然后使用相同的
    current\u time
    ,将其转换为ETC或访问者使用的任何时区,然后将其转换为字符串,最后通过Ajax将其传递回JavaScript。我希望这是有意义的。@hobbes3我假设,由于您通过JSON发送的内容仅用于显示,因此它不必与存储在数据库中的时间相匹配,精确到微秒,因此,使用两个不同的
    datetime
    对象是非常安全的,因此您根本不必在UTC和本地时区之间来回转换。但是,您始终可以在任意方向上使用
    replace(tz=thetz)
    ,但是
    timezone.now()作为一个方便的函数,其目的是能够轻松地为您提供一个时区感知的本地时间。