Pytz - 时区激活但时间错误。我错过了什么吗?

时间:2017-07-09 19:08:19

标签: django python-2.7 timezone pytz

在我的主页面上,我获得了以下视图定义触发

def initializeTimeZone(request):
    tzone = request.GET.get("tzone") # returns 'America/Los_Angeles'
    user_time_zone = request.session.get('user_time_zone', None)
    try:
        if user_time_zone is None:
            request.session['user_time_zone'] = tzone
            timezone.activate(pytz.timezone(tzone)) #--->is this correct ? 
            time = datetime.datetime.now().strftime(settings.DATE_TIME_OBJECT_FORMATTING) #--->Wrong
        return HttpResponse("OK")
    except Exception as ex:
        print >> sys.stderr, str(ex)

现在,当我稍后在

上做这样的事情时
time = datetime.datetime.now().strftime(settings.DATE_TIME_OBJECT_FORMATTING)

我得错了日期 '2017-07-09 19:01:33'

关于我可能做错的任何建议。

1 个答案:

答案 0 :(得分:1)

这是我确保正确存储和显示时区和日期时间的一般方法。

首先确保USE_TZ = True文件中的settings.py并确保其中TIME_ZONE='UTC'

因此,在向数据库添加日期时,请确保它们采用UTC格式,以避免出现多个时区或夏令时的问题。

我通常根据本文底部的示例使用中间件设置会话时区。我只是将它更改为不再使用已弃用的MiddlewareMixin(所以你需要django 1.10+来关注这个,否则看下面更多)

import pytz

from django.utils import timezone

# make sure you add `TimezoneMiddleware` appropriately in settings.py
class TimezoneMiddleware(object):
    """
    Middleware to properly handle the users timezone
    """

    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        # make sure they are authenticated so we know we have their tz info.
        if request.user.is_authenticated():
            # we are getting the users timezone string that in this case is stored in 
            # a user's profile
            tz_str = request.user.profile.timezone
            timezone.activate(pytz.timezone(tz_str))
        # otherwise deactivate and the default time zone will be used anyway
        else:
            timezone.deactivate()

        response = self.get_response(request)
        return response

在调整为正确使用用户时区后,请确保将其添加到settings.py

中的中间件

现在,当在模板中访问datetime对象时,它们将自动从数据库的“UTC”格式转换为用户所在的任何时区。只需访问datetime对象,并假设先前的中间件设置其时区设置得当。

{{ my_datetime_value }}

如果您希望对用户的时区是否使用进行细粒度控制,请查看以下内容:

{% load tz %}
{% localtime on %}
    {# this time will be respect the users time zone #}
    {{ your_date_time }}
{% endlocaltime %}

{% localtime off %}
    {# this will not respect the users time zone #}
    {{ your_date_time }}
{% endlocaltime %}

https://docs.djangoproject.com/en/1.11/topics/i18n/timezones/

启用时区支持

首先,确保USE_TZ = True文件中的settings.py。同时将默认时区值设置为TIME_ZONE,例如TIME_ZONE='UTC'。查看完整的时区列表here

如果USE_TZ为False,TIME_ZONE将是Django用于存储所有日期时间的时区。启用USE_TZ时,TIME_ZONE是Django用于在模板中显示日期时间以及解释在表单中输入的日期时间的默认时区。

启用时区支持后,django会将datetime数据存储在数据库中作为时区UTC

设置会话时区

Python的datetime.datetime个对象具有tzinfo属性,用于存储时区信息。设置属性时,对象被视为Aware,当未设置属性时,它被视为Naive。

为确保时区天真或有意识,您可以使用.is_naive().is_aware()

如果您的USE_TZ文件中已启用settings.py,只要您在{datetime中设置了默认TIME_ZONEsettings.py就会附加时区信息。 1}}

虽然在某些情况下此默认时区可能不错,但可能不够,尤其是在多个时区处理用户时。为了实现这一点,必须使用中间件。

import pytz

from django.utils import timezone

# make sure you add `TimezoneMiddleware` appropriately in settings.py
class TimezoneMiddleware(object):
    """
    Middleware to properly handle the users timezone
    """

    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        # make sure they are authenticated so we know we have their tz info.
        if request.user.is_authenticated():
            # we are getting the users timezone that in this case is stored in 
            # a user's profile
            tz_str = request.user.profile.timezone
            timezone.activate(pytz.timezone(tz_str))
        # otherwise deactivate and the default time zone will be used anyway
        else:
            timezone.deactivate()

        response = self.get_response(request)
        return response

有一些新事物正在发生。在__call__中,我们正在处理时区数据的设置。首先,我们确保用户已通过身份验证,以确保我们为此用户提供时区数据。一旦我们知道了,我们就会使用timezone.activate()为用户会话激活时区。为了将时区字符串转换为datetime可用的时区字符串,我们使用pytz.timezone(str)

现在,当在模板中访问datetime对象时,它们将自动从数据库的“UTC”格式转换为用户所在的任何时区。只需访问datetime对象,并假设先前的中间件设置其时区设置得当。

{{ my_datetime_value }}

如果您希望对用户的时区是否使用进行细粒度控制,请查看以下内容:

{% load tz %}
{% localtime on %}
    {# this time will be respect the users time zone #}
    {{ your_date_time }}
{% endlocaltime %}

{% localtime off %}
    {# this will not respect the users time zone #}
    {{ your_date_time }}
{% endlocaltime %}

注意,此方法仅适用于Django 1.10及其中。要从1.10之前支持django,请查看MiddlewareMixin