在我的应用程序中,我使用时区(USE_TZ=True
),我在代码中创建的所有日期都知道UTC datetime
对象(我使用django.util.timezone.now
表示当前日期和以下帮助程序函数来确保实例中的所有日期都是我期望的:)
@classmethod
def asUTCDate(cls, date):
if not timezone.is_aware(date):
return timezone.make_aware(date, timezone.utc)
return date.replace(tzinfo=timezone.utc)
我还使用此代码片段强制执行对幼稚/意识日期的检查(如文档中建议的那样):
import warnings
warnings.filterwarnings(
'error', r"DateTimeField .* received a naive datetime",
RuntimeWarning, r'django.db.models.fields')
正如我目前所理解的,这是正确的方法(这是 django 文档中的一句话:"这个问题的解决方案是在代码中使用 UTC,并且仅在与最终用户交互时使用本地时间"),而且似乎我的应用程序处理日期非常好......但我刚刚针对使用 Django 1.6 __hour
的模型实现了一个过滤器,并根据用户时区强制提取,结果如下:
django_datetime_extract('hour', "object"."date", Europe/Rome) = 15
但这打破了我的查询,因为我期望的一些结果不包括在集合中,但是当我使用__range
在日期之间搜索时,它似乎按预期工作(返回日期在范围内的对象)...所以在我看来,Django 只在查询中考虑__hour
过滤器的时区......但我不明白为什么...我假设 UTC 在任何地方都使用,除了在根据用户 tz 格式化显示日期的模板中,但也许这不是真的。所以我的问题是:我处理时区的方式是否正确?__hour
过滤器是错误的还是什么?
看起来你在约会上做正确的事情。 但是,任何日期相关功能(如按小时筛选)的所有文档都包含以下注释:
当USE_TZ为 True 时,日期时间字段将转换为当前时间 过滤前的区域。
对于range
筛选器,此注释不存在,因为range
不仅可以用于筛选日期,还可以用于筛选其他类型的类型,例如整数和字符。 即它不一定知道日期时间。
从本质上讲,问题归结为:当时间位于本地时区时,"与用户交互"与时间在UTC时区的内部界限之间,您在哪里划清界限? 在您的情况下,您可以想象用户在搜索框中输入以搜索 hour==3。 例如,这是否意味着您的表单代码应该在 hour==3 和 UTC 等效值之间进行转换? 这将需要一种特殊的表格。小时场。 或者,也许值 (3) 应该直接提供给查询,我们知道我们正在搜索小时字段,因此需要进行转换。
我们真的必须遵循这方面的文档。
- 将使用任何专用日期/时间筛选
- 函数根据日期/时间字段进行筛选的值将被视为位于用户的本地时区。
- 如果对日期使用
range
筛选器,则不会发生时间转换,因此应将用户输入的本地时间值转换为 UTC。