return 使用 Django 查询的活动时区中的日期时间
return datetimes in the active timezone with a django query
我正在尝试从 table 中检索最后 n 小时的行并在给定时区中打印它们的日期时间,给出打印日期时使用的时区,我正在尝试使用 activate 来制作 django return 具有正确时区的日期时间,但 returns 日期为 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 为我执行此操作,我是否有时会遗漏激活函数?
编辑
这是我的模型,您可以看到要显示的时区保存在 "monitor" 模型上:
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()
您可以使用django.utils
中的now()
函数,但您需要在设置中设置两个变量:USE_TZ
和TIME_ZONE
,第一个是True
和另一个将用于生成日期时间的默认时区。
您可以在 django 文档中查看更多信息 here。
经过一些研究后,我注意到 Django 总是 returns 日期时间为 UTC,您可以通过使用 datetime.astimezone(timezone) 方法或激活某个特定的方法在正确的时区中解释它们时区。
django active 函数只是改变了日期时间在模板上的呈现方式,但实际上并没有本地化时区。
如果您发现自己在循环中执行 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))
)
这将 return 正确时区的日期时间或日期。您可以将其他 Trunc* 函数用作 shorthand。如果您只需要 datetime.date
s
,TruncDate
特别有用
这会将日期计算卸载到数据库,通常会大大降低代码复杂性和提高速度(在我的例子中,超过 650 万 timezone.localtime(ts)
贡献了总 CPU 时间的 25% )
关于 TruncMonth 和时区的注意事项
不久前我发现我无法从 TruncMonth
或 TruncQuarter
中获得 'proper' 个月:1 月 1 日将成为 12 月 31 日。
TruncMonth 使用当前活动的时区,因此(正确地)2019-01-01T00:00:00Z 的 datetime
被转换为前一天对于任何与 UTC 有正偏移的时区(西方欧洲和更东边的任何地方)。
如果您只对事件 datetime
的 'pure month' 感兴趣(如果您使用的是 TruncMonth,则可能是)这没有帮助,但是如果您 timezone.activate(timezone.utc)
在执行查询(即评估您的 QuerySet),您将获得预期的结果。请记住,从您的午夜到 UTC 的午夜发生的事件将归入上个月(并且以相同的方式从您时区的午夜到 UTC 的午夜 datetime
s 将转换为 'wrong' 月份)
我正在尝试从 table 中检索最后 n 小时的行并在给定时区中打印它们的日期时间,给出打印日期时使用的时区,我正在尝试使用 activate 来制作 django return 具有正确时区的日期时间,但 returns 日期为 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 为我执行此操作,我是否有时会遗漏激活函数?
编辑
这是我的模型,您可以看到要显示的时区保存在 "monitor" 模型上:
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()
您可以使用django.utils
中的now()
函数,但您需要在设置中设置两个变量:USE_TZ
和TIME_ZONE
,第一个是True
和另一个将用于生成日期时间的默认时区。
您可以在 django 文档中查看更多信息 here。
经过一些研究后,我注意到 Django 总是 returns 日期时间为 UTC,您可以通过使用 datetime.astimezone(timezone) 方法或激活某个特定的方法在正确的时区中解释它们时区。
django active 函数只是改变了日期时间在模板上的呈现方式,但实际上并没有本地化时区。
如果您发现自己在循环中执行 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))
)
这将 return 正确时区的日期时间或日期。您可以将其他 Trunc* 函数用作 shorthand。如果您只需要 datetime.date
s
TruncDate
特别有用
这会将日期计算卸载到数据库,通常会大大降低代码复杂性和提高速度(在我的例子中,超过 650 万 timezone.localtime(ts)
贡献了总 CPU 时间的 25% )
关于 TruncMonth 和时区的注意事项
不久前我发现我无法从 TruncMonth
或 TruncQuarter
中获得 'proper' 个月:1 月 1 日将成为 12 月 31 日。
TruncMonth 使用当前活动的时区,因此(正确地)2019-01-01T00:00:00Z 的 datetime
被转换为前一天对于任何与 UTC 有正偏移的时区(西方欧洲和更东边的任何地方)。
如果您只对事件 datetime
的 'pure month' 感兴趣(如果您使用的是 TruncMonth,则可能是)这没有帮助,但是如果您 timezone.activate(timezone.utc)
在执行查询(即评估您的 QuerySet),您将获得预期的结果。请记住,从您的午夜到 UTC 的午夜发生的事件将归入上个月(并且以相同的方式从您时区的午夜到 UTC 的午夜 datetime
s 将转换为 'wrong' 月份)