1

In Django you have a TIME_ZONE setting, which, as I understand, somehow patches the standard date and time packages in runtime, making them think the application is working in the time zone specified. As a result, generic Python methods for determining local time zone do not work (they just show the configured time zone).

I can evaluate the link of /etc/localtime like in this answer or use another Linux-specific method but I am concerned about the portability issue, as some developers run the app on Windows.

Can I find out in a platform independent way what was the original time zone on the machine?

greatvovan
  • 2,439
  • 23
  • 43
  • What do you mean by "local machine"? Are we talking about the server the Django app is running on or the client machine browsing the app? – Selcuk Mar 03 '21 at 01:45
  • 1
    @Selcuk I should have been more specific: the time zone settings in the OS user account which runs the Django server application. – greatvovan Mar 03 '21 at 01:50
  • Django sets an environment variable but doesn't patch anything. You can try the [tzlocal](https://github.com/regebro/tzlocal) package to get the server timezone on both windows and unix. – Kevin Christopher Henry Mar 03 '21 at 02:01
  • @KevinChristopherHenry Maybe I am missing something, but like I posted in my question, every single method by the provided link (including tzlocal package) returns the zone configured in `TIME_ZONE`. I don't know how else to explain it, other than by altering the standard packages. E.g. `datetime.now().astimezone().tzinfo` is showing me the correct time zone in pure Python, but is showing the `TIME_ZONE` time zone when running the Django app. – greatvovan Mar 03 '21 at 02:12
  • @KevinChristopherHenry the documentation gives some insight on that: "On Unix environments, Django sets the os.environ['TZ'] variable to the time zone you specify in the TIME_ZONE setting". This is what seems to affect work of the standard date/time packages. The question is how to fallback to the default method of getting time zone, not affecting other places where date/time functions are used. – greatvovan Mar 03 '21 at 02:21
  • [Looks like](https://github.com/django/django/blob/a948d9df394aafded78d72b1daa785a0abfeab48/django/conf/__init__.py#L169) the issue is that Django is calling [`time.tzset()`](https://docs.python.org/3/library/time.html#time.tzset). Not sure how you can access the original value. – Kevin Christopher Henry Mar 03 '21 at 02:33
  • since `time.tzset()` is only for Unix systems, what does django do on Windows? Anyways, a (hacky) work-around could be to use geo-location, e.g. `os.system('curl http://ip-api.com/line?fields=timezone')` - note however that this will not necessarily return the time zone of the machine, just its location. – FObersteiner Mar 03 '21 at 07:42

1 Answers1

0

As there were no answers, I will post a workaround here.

Though we cannot recover the initial time zone (without affecting the current settings), we can obtain and save it before Django's initialization. For example:

  1. For running locally, we can augment manage.py:
cmd = sys.argv[1] if len(sys.argv) >= 2 else ""
if cmd == "runserver":
    from tzlocal import get_localzone
    os.environ['MACHINE_TIME_ZONE'] = get_localzone().tzname(None)
# ...
execute_from_command_line(sys.argv)
  1. For production, the way depends on how you launch the application. For example, if you are using Gunicorn, you can put it into gunicorn.conf.py or wsgi.py. The main thing is tu put it somewhere before loading Django libraries:
from tzlocal import get_localzone
os.environ['MACHINE_TIME_ZONE'] = get_localzone().tzname(None)

Later you can access this environment variable to retrieve the value.

greatvovan
  • 2,439
  • 23
  • 43