[Django]-Django 1.11 – How can I ensure TruncYear to produce Zulu time

6👍

The very first thing I noted here is, you are using serializers.DateTimeField–DRF doc field for a year representation, where the year always will be a positive integer.


Regarding the timezone issue, Django uses the TIME_ZONE settings while querying from the database. Here is the minimal SQL query in postgress that happens when you do so,

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

But, fortunately, you can specify the target timezone (in your case, its UTC) with the help of tzinfo parameter in the TruncYear class.

Example

import pytz

Tracking.objects.annotate(year=TruncYear('created_at', tzinfo=pytz.UTC))

To show year in the json reponse, change your serializer as,

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']

References

  1. Postgress AT TIME ZONE
  2. Postgress date_trunc
  3. DRF Serializer source argument
👤JPG

0👍

I’ve checked sources of Django Rest Framework and it looks like it uses “current timezone” by default for DateTimeField but you can set it in a force manner by passing default_timezone equal to "pytz.timezone('Zulu')". This way it will return the field value in the required timezone.

I’ve played with that a bit and for me it works as expected. For example for Europe/Moscow for my test serializer (in my project) I have output like

{
    "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"
  }

And for Zulu timezone I have it like

  {
    "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"
  }

My test field declaration is

created_at = serializers.DateTimeField(format='iso-8601', default_timezone=pytz.timezone('Zulu'))

It seems like in your source code you override “current timezone” but don’t set it to a default one or etc and that’s why it works right after the server restart and stops in a few hours (when a request sets the wrong timezone). So you have 2 ways to fix it – declare your fields as I did above using the default_timezone param or find where the current timezone value is changed). The easiest solution for the case, of course, is declaring the field timezone required but in general, of course, it should work without bugs 🙂

More information:

Leave a comment