这是我确保正确存储和显示时区和日期时间的一般方法。
首先确保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()
如果您在settings.py 文件中启用了USE_TZ,只要在settings.py 中设置了默认TIME_ZONE,datetime 就会附加时区信息
虽然此默认时区在某些情况下可能很好,但可能还不够,尤其是在您处理多个时区的用户时。为了做到这一点,必须使用中间件。
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() 为用户会话激活时区。为了将时区字符串转换为日期时间可用的字符串,我们使用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