我使用的是 Django 1.11 和 Postgres 9.4。
如何确保 TruncYear 生成祖鲁时间 (2019-10-01T00:00:00Z)。我注意到它创建带有时区的日期时间,如下所示 (2017-01-01T00:00:00+03:00)
这是我的 TruncYear 查询集代码:
from django.db.models import Count
from django.db.models.functions import TruncMonth, TruncYear, TruncDay, TruncHour
tracking_in_timeseries_data = Tracking.objects.annotate(
year=TruncYear('created_at')).values('year', 'venue').annotate(
count=Count('employee_id', distinct = True)).order_by('year')
>>> for exp in tracking_in_timeseries_data:
... print(exp['year'], exp['venue'], exp['count'])
2017-01-01 00:00:00+00:00 4 1
2019-01-01 00:00:00+00:00 2 2
2019-01-01 00:00:00+00:00 3 1
2019-01-01 00:00:00+00:00 4 1
2019-01-01 00:00:00+00:00 5 1
2019-01-01 00:00:00+00:00 6 1
>>> tracking_in_timeseries_data
<QuerySet [{'venue': 4, 'year': datetime.datetime(2017, 1, 1, 0, 0, tzinfo=<UTC>), 'count': 1}, {'venue': 2, 'year': datetime.datetime(2019, 1, 1, 0, 0, tzinfo=<UTC>), 'count': 2}, {'venue': 3, 'year': datetime.datetime(2019, 1, 1, 0, 0, tzinfo=<UTC>), 'count': 1}, {'venue': 4, 'year': datetime.datetime(2019, 1, 1, 0, 0, tzinfo=<UTC>), 'count': 1}, {'venue': 5, 'year': datetime.datetime(2019, 1, 1, 0, 0, tzinfo=<UTC>), 'count': 1}, {'venue': 6, 'year': datetime.datetime(2019, 1, 1, 0, 0, tzinfo=<UTC>), 'count': 1}]>
如果我序列化它会产生这样的结果:
序列化器.py
class TimeseriesYearSerializer(serializers.ModelSerializer):
venue = VenueTSSerializer(read_only=True)
year = serializers.DateTimeField(read_only=True)
count = serializers.IntegerField(read_only=True)
class Meta:
model = Tracking
fields = ['venue', 'year', 'count']
输出:
[
{
"count": 1,
"year": "2017-01-01T00:00:00+03:00",
"venue_id": 2
},
{
"count": 1,
"year": "2018-01-01T00:00:00+03:00",
"venue_id": 1
},
{
"count": 1,
"year": "2018-01-01T00:00:00+03:00",
"venue_id": 2
},
{
"count": 3,
"year": "2019-01-01T00:00:00+03:00",
"venue_id": 1
},
{
"count": 3,
"year": "2019-01-01T00:00:00+03:00",
"venue_id": 2
}
]
如何确保 TruncYear 查询集生成祖鲁时间的日期时间字符串,如 2019-10-01T00:00:00Z,而不是时区 2019-01-01T00:00:00+03:00。
更新: 我注意到我通过重新启动 django 服务临时修复了这个问题。
sudo supervisorctl stop all
sudo supervisorctl start all
然后就能够像这样产生 Z 时间 2019-10-01T00:00:00Z 但几个小时后,它开始生成像这样的时区时间格式 2017-01-01T00:00:00+03:00
我还注意到,如果我重新启动服务器,它将不会有 Z 时间。我必须执行 Supervisorctl stop 和 start 然后它暂时似乎可以修复它。
这是我的主管重新启动的代码片段
/home/user/myapp/gunicorn_start.bash
/etc/supervisor/conf.d/myapp.conf
https://gist.github.com/axilaris/01525b78fcdc03071fcd34818820d7f1
这是我的服务器版本 Ubuntu 16.04.3 LTS
可能是什么问题以及如何修复它,以便始终产生 Zulu 时间。
最佳答案
我在这里注意到的第一件事是,您正在使用 serializers.DateTimeField
--DRF doc用于年份表示的字段,其中年份始终是正整数 .
关于时区问题,Django使用TIME_ZONE
settings在从数据库查询时。这是 postgress 中执行此操作时发生的最小 SQL 查询,
SELECT a,b,c,<b>DATE_TRUNC('year', "tracking_table"."created_at" AT TIME ZONE 'YOUR_TIME_ZONE_VALUE') AS "year"</b> FROM "tracking_table
但是,幸运的是,您可以在 tzinfo
的帮助下指定目标时区(在您的情况下为 UTC) TruncYear
中的 参数类。
示例
<b>import pytz</b>
Tracking.objects.annotate(year=<b>TruncYear('created_at', tzinfo=pytz.UTC)</b>)
<小时/>
要在 json 响应中显示年份,请将序列化器更改为,
class TimeseriesYearSerializer(serializers.ModelSerializer):
venue = VenueTSSerializer(read_only=True)
<b>year = serializers.IntegerField(read_only=True, source='year.year')</b>
count = serializers.IntegerField(read_only=True)
class Meta:
model = Tracking
fields = ['venue', 'year', 'count']
<小时/>
引用文献
关于python - Django 1.11 - 如何确保 TruncYear 生成 Zulu 时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58751806/