Python Django 1.11-我如何确保TruncYear生产祖鲁时间

Python Django 1.11-我如何确保TruncYear生产祖鲁时间,python,django,postgresql,datetime,django-1.11,Python,Django,Postgresql,Datetime,Django 1.11,我正在使用Django1.11和Postgres9.4 我如何确保TruncYear生产祖鲁时间(2019-10-01T00:00:00Z)。我注意到它创建了带有如下时区的datetime(2017-01-01T00:00:00+03:00) 以下是我的TruncYear查询集代码: from django.db.models import Count from django.db.models.functions import TruncMonth, TruncYear, TruncDay,

我正在使用Django1.11和Postgres9.4

我如何确保TruncYear生产祖鲁时间(2019-10-01T00:00:00Z)。我注意到它创建了带有如下时区的datetime(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}]>
输出:

[
    {
      "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 queryset在Zulu时间生成日期时间字符串,如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时间。我必须先停止再启动,然后它暂时似乎可以修复它

下面是我的代码片段,供主管重新启动

/home/user/myapp/gunicorn_start.bash
/etc/supervisor/conf.d/myapp.conf
https://gist.github.com/axilaris/01525b78fcdc03071fcd34818820d7f1
这是我的服务器版本Ubuntu 16.04.3 LTS


问题可能是什么,以及如何修复它以使其始终生成Zulu时间。

我已经检查了Django Rest框架的源代码,它看起来像是默认情况下对
日期时间域使用了“”,但是您可以通过将
默认\u时区
等于
pytz.timezone('Zulu')”
来强制设置它。这样,它将返回所需时区中的字段值

我已经玩了一点,对我来说,它就像预期的那样工作。例如,对于
Europe/Moscow
,对于我的测试序列化程序(在我的项目中),我的输出如下

{
    "id": 1,
    "title": "test 123",
    "level": 0,
    "slug": "test-123",
    "icon_code": "123",
    "image": null,
    "brand": false,
    "children": [],
    "created_at": "2019-12-09T01:55:08.438442+03:00"
  }
对于Zulu
时区,我有类似的

  {
    "id": 1,
    "title": "test 123",
    "level": 0,
    "slug": "test-123",
    "icon_code": "123",
    "image": null,
    "brand": false,
    "children": [],
    "created_at": "2019-12-08T22:55:08.438442Z"
  }
我的测试场声明是

created_at = serializers.DateTimeField(format='iso-8601', default_timezone=pytz.timezone('Zulu'))
在源代码中,您似乎覆盖了“当前时区”,但没有将其设置为默认时区等,这就是为什么它在服务器重新启动后立即工作,并在几个小时后停止(当请求设置错误的时区时)。因此,您有两种方法来修复它-使用
default_timezone
param或查找当前时区值的更改位置,如上所述声明字段。当然,这种情况下最简单的解决方案是声明所需的字段时区,但通常情况下,它应该可以正常工作,而不会出现错误:)

更多信息:

  • (查看
    default\u时区
    param)

我在这里注意到的第一件事是,您使用字段表示,其中始终是一个正整数


关于时区问题,Django使用while从数据库查询。这是postgress中的最小SQL查询,当您这样做时会发生

SELECT a,b,c,DATE_TRUNC('year', "tracking_table"."created_at" AT TIME ZONE 'YOUR_TIME_ZONE_VALUE') AS "year" FROM "tracking_table

要在json响应中显示年份,请将序列化程序更改为

class TimeseriesYearSerializer(serializers.ModelSerializer):
    venue = VenueTSSerializer(read_only=True)
    year = serializers.IntegerField(read_only=True, source='year.year')
    count = serializers.IntegerField(read_only=True)

    class Meta:
        model = Tracking
        fields = ['venue', 'year', 'count']
class TimeseriesYearSerializer(serializers.ModelSerializer):
地点=VenueTSSerializer(只读=真)
year=serializers.IntegerField(只读=True,source='year.year')
计数=序列化程序。整型字段(只读=真)
类元:
模型=跟踪
字段=[‘地点’、‘年份’、‘计数’]

工具书类




  • 为什么年需要一个
    datetime字段而不是IntegerField?我已经实现了这个-Tracking.objects.annotate(year=TruncYear('created_at',tzinfo=pytz.UTC))。我给它一些时间,如果它能坚持,到目前为止,它已经坚持了几个小时。将在明天更新我的插件,你所说的暂停是什么意思?意味着这个解决方案目前正在运行。我只需要像上一个查询集那样观察更长的时间,一天后,它会再次显示时区。到目前为止,它看起来还可以,但我需要观察。太好了…让我知道结果。是的,一天多之后,它仍然得到时间。谢谢。
    
    import pytz
    
    Tracking.objects.annotate(year=TruncYear('created_at', tzinfo=pytz.UTC))
    class TimeseriesYearSerializer(serializers.ModelSerializer):
        venue = VenueTSSerializer(read_only=True)
        year = serializers.IntegerField(read_only=True, source='year.year')
        count = serializers.IntegerField(read_only=True)
    
        class Meta:
            model = Tracking
            fields = ['venue', 'year', 'count']