1

I'm having lot's of troubles with TimeZones in my Django application.

For explanation purposes I'll jump right to the example :

I have an object which has a TimeField(null=True, blank=True), and I basically want to show this time depending on the users timezone.

I have a Middleware class which activates the timezone to the authenticated user :

#'middleware.py'


import pytz

from django.utils import timezone


class TimezoneMiddleware(object):
    """
    Middleware to properly handle the users timezone
    """

    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        if request.user.is_authenticated:
            timezone.activate(pytz.timezone(request.user.timezone))
        else:
            timezone.deactivate()

        response = self.get_response(request)
        return response

Next to this, I'm pulling timezones from User model field timezone = models.CharField(max_length=128, choices=[(tz, tz) for tz in ['UTC'] + pytz.country_timezones('US')], default="UTC") which basically tells me the timezone user selected.

And that's all good until I need to render the time adopted to the users timezone.

So In my case user has the 'Pacific/Honolulu' timezone. Object time field was saved to 'American/New_York' timezone, and I'm still getting the same time no matter which timezone I select.

What am I doing wrong?

(I was fallowing the official docs for this)

This is my template :

{% load tz %}
{% get_current_timezone as TIME_ZONE %}

{% for object in objects %}
    {% localtime on %}
        {{ object.min_reservation_time }}
    {% endlocaltime %}
{% endear %}

Also - when I try to render {{TIME_ZONE}} in this exact template - I get nothing.

This is my settings.py :

TIME_ZONE = 'UTC' # Default timezone if custom timezone is not activated by middleware

USE_I18N = True

USE_L10N = True

USE_TZ = True

So one more time, users selects the timezone, middleware process it if the user is logged in, and ...nothing changes for some reason.

dev.ink
  • 380
  • 5
  • 21

1 Answers1

1

You'd be doing the right things—if you had a DateTimeField. But, as the documentation says:

Django only supports naive time objects and will raise an exception if you attempt to save an aware time object, as a timezone for a time with no associated date does not make sense.

So none of Django's time zone support applies to a TimeField. If you really do want to use a TimeField, and adjust the values depending on the user's timezone, you'll have to do so manually.

Kevin Christopher Henry
  • 46,175
  • 7
  • 116
  • 102
  • Thanks! I was afraid of this -.- – dev.ink Oct 12 '20 at 12:51
  • @dev.ink: My first suggestion is to carefully consider this conclusion, representing the consensus of experts: "a timezone for a time with no associated date does not make sense". Let's take your example of Honolulu and New York. One uses DST and the other doesn't, so the offset between them changes depending on the date. So it doesn't make sense to try and adjust the time between them without knowing the day of the year you're talking about. You will make your life a lot easier by rethinking your architecture to account for this, and using `DateTimeFields`. – Kevin Christopher Henry Oct 12 '20 at 13:32
  • In my case, I have an object with opening and closing hours, and I cannot set or define DATE for opening hours, because the date will be different every day if you know what I mean. What I can do though is to save todays date every time before the page loads, and change the db value of year, month and day, and keep the time. But that's not a good practice I think. – dev.ink Oct 12 '20 at 13:34
  • But opening and closing hours should be affected by the timezone so the users can see them depending on their zone. – dev.ink Oct 12 '20 at 13:34
  • @dev.ink: So you want to take the time, and display it to the user as if it was in their timezone, on that particular day? Sure, you can do that easily enough by combining the time and today's date into an aware datetime in your view. The other problem, though, is that you say this: "Object time field was saved to 'American/New_York' timezone". These are naive times, so they are not saved with any timezone information attached. There is no way to know what timezone they were saved in. – Kevin Christopher Henry Oct 12 '20 at 15:14
  • What if I save the time in the selected timezone, using tzinfo on save? – dev.ink Oct 12 '20 at 18:20
  • Object was saved like this : ```datetime(year=todays_year, month=todays_month, day=todays_day, hour=form.cleaned_data.get('max_reservation_time').hour, minute=form.cleaned_data.get('max_reservation_time').minute, tzinfo=pytz.timezone(prop.timezone))``` Where prop.timezone is equal to 'America/New_York' – dev.ink Oct 12 '20 at 18:35
  • Also, when I save the object like this, still after the saving, when I try to get tzinfo on DateTime field, I get UTC even if I added timezone awareness. – dev.ink Oct 12 '20 at 19:04
  • @dev.ink: I don't quite follow what you're proposing, and comments are not a good place to describe a new architecture. You should write up your proposal in detail, either by editing the question or starting a new question. – Kevin Christopher Henry Oct 13 '20 at 12:07
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/222963/discussion-between-dev-ink-and-kevin-christopher-henry). – dev.ink Oct 13 '20 at 12:11