2

我正在尝试从表中检索最后 n 小时的行并在给定的时区打印它们的日期时间,给出打印日期时要使用的时区,我正在尝试使用 activate 使 django 返回具有正确时区的日期时间但是它以 UTC 格式返回日期。

这是我当前的代码:

min_time = datetime.datetime.now(link.monitor.timezone) - datetime.timedelta(hours=period)

timezone.activate(link.monitor.timezone)
rows = TraceHttp.objects.values_list('time', 'elapsed').filter(time__gt=min_time,link_id=link_id,elapsed__gt=0)

array = []
for row in rows:
    array.append((row[0].astimezone(link.monitor.timezone),row[1]))

我想避免使用 astimezone 函数并让 Django 为我执行此操作,有时我会错过激活函数吗?

编辑

这是我的模型,您可以看到要显示的时区保存在“监视器”模型上:

class Link(models.Model):
   ...
   monitor = models.ForeignKey(Monitor)
   ...

class Monitor(models.Model):
    ...
    timezone = TimeZoneField(default='Europe/London')

class TraceHttp(models.Model):
    link = models.ForeignKey(Link)
    time = models.DateTimeField()
    elapsed = models.FloatField()
4

3 回答 3

6

经过一番研究,我注意到 Django 总是将日期时间返回为 UTC,您可以通过使用 datetime.astimezone(timezone) 方法或激活某个时区来在正确的时区解释它们。

django active 函数只是改变了在模板上呈现日期时间的方式,但实际上并没有本地化时区。

于 2015-10-29T02:57:40.097 回答
5

如果你发现自己在做几百万次timezone.localtime(dt_value)dt_value.astimezone(tzifo)循环几百万次来计算你所在时区的当前日期,那么从 1.10 <= django.VERSION <= 2.1 开始,可能最好的方法是使用 django.db.models.functions .Trunc 和相关函数,即使用如下查询集:

from django.db.models.functions import Trunc, TruncDate

qs = MyModel.objects.filter(...).values(
    'dtime',
    ...,
    dtime_at_my_tz=Trunc('dtime', 'second', tzinfo=yourtz),
    date_at_my_tz=TruncDate('dtime', tzinfo=yourtz),
    month=TruncDate(Trunc('dtime', 'month', tzinfo=yourtz)),
    quarter=TruncDate(Trunc('dtime', 'quarter', tzinfo=yourtz))
)

这将返回正确时区的日期时间或日期。您可以使用其他 Trunc* 函数作为速记。TruncDate如果您只需要datetime.dates ,则特别有用

这会将日期计算卸载到数据库中,通常会大大降低代码复杂性并提高速度(在我的例子中,超过 650 万timezone.localtime(ts)个贡献了总 CPU 时间的 25%)

关于 TruncMonth 和时区的注意事项

不久前,我发现我无法从TruncMonthor中获得“适当的”月份TruncQuarter:1 月 1 日将变成 12 月 31 日。

TruncMonth 使用当前活动的时区,因此(正确地)datetime2019-01-01T00:00:00Z 的 a 被转换为与 UTC 有正偏移的任何时区(西欧和更远东的任何地方)的前一天。如果您只对事件的“纯月份”感兴趣datetime(如果您使用的是 TruncMonth,那么您可能会感兴趣)这没有帮助,但是如果您timezone.activate(timezone.utc)在执行查询之前(即评估您的 QuerySet),您会得到预期的结果。请记住,从您的午夜到 UTC 的午夜发生的事件将低于上个月(同样,datetime从您的时区的午夜到 UTC 的午夜将转换为“错误”月份)

于 2019-04-02T05:53:06.693 回答
0

您可以使用 Django.utils 中的 now() 函数,但是,您需要在设置中设置两个变量。USE_TZ 和 TIME_ZONE,第一个为 true,另一个为用于生成日期时间的默认时区。您可以在此处查看 django 文档中的更多信息

于 2015-10-20T22:35:06.183 回答