0

I required some extra date/time formats in addition to ones Django ships with, sI created these new formats:

  • SHORT_TIME_FORMAT
  • FILE_DATETIME_FORMAT
  • ISO8601_DATETIME_FORMAT.

So that I could use them in templates like this:

{{ value|date:"SHORT_DATE_FORMAT" }}

And In code like this:

from django.utils import formats

formats.date_format(value, `SHORT_TIME_FORMAT`)

I created the following code in utils/time/formats.py:

from collections import ChainMap

from django.utils import formats

DJANGO_DATETIME_FORMATS = {
    'DATETIME_FORMAT': 'd M Y, H:i',
    'DATE_FORMAT': 'j M Y',
    'TIME_FORMAT': 'H:i:s',
    'SHORT_DATETIME_FORMAT': 'Y-m-d H:i:s',
    'SHORT_DATE_FORMAT': 'Y-m-d',
    'MONTH_DAY_FORMAT': 'd M',
    'YEAR_MONTH_FORMAT': 'Y M',
}

EXTRA_DATETIME_FORMATS = {
    'SHORT_TIME_FORMAT': 'H:i',
    'FILE_DATETIME_FORMAT': 'Y-m-d H.i.s',
    'ISO8601_DATETIME_FORMAT': 'c',  # Compatible with Javascript passing
}

def set_formats(globals_dict):
    """Returns a set of datetime formats for use across the whole project

    Contains a union of the default formats along with the additional ones.
    To add a new format, one has to perform the following two actions:
        1. Add the name of the format to formats.FORMAT_SETTINGS
        2. Add a variable with the same name as the variable to the settings.py
           file with the value assigned to the required format.
    globals_dict is the globals from the settings.py file
    """
    formats.FORMAT_SETTINGS = frozenset(formats.FORMAT_SETTINGS | EXTRA_DATETIME_FORMATS.keys())

    all_formats = ChainMap(DJANGO_DATETIME_FORMATS, EXTRA_DATETIME_FORMATS)
    for setting, value in all_formats.items():
        globals_dict[setting] = value

However when I add it to my settings.py file as so:

# settings.py
from utils.time.formats import set_formats

set_formats(globals())

My timezone changes to Chicargo, even though in settings.py I have:

TIME_ZONE = 'Africa/Johannesburg'

After research I found out that Django's default timezone is Chicargo, which is 7 Hrs behind me (I am UTC+02).

I can test it like this:

$ python manage.py shell
> from django.utils import timezone
> from django.conf import settings
> print(f"The settings.py TIME_ZONE value is: {settings.TIME_ZONE=}")
The settings.py TIME_ZONE value is: settings.TIME_ZONE='Africa/Johannesburg'
> print("Using Django local time, now is:")
Using Django local time, now is:
> print(timezone.localtime())
2022-07-27 20:54:35.293958+02:00

If I don't use set_formats, the datetime is correctly in my local time, if I add my set_formats function, then datetime is 7 Hrs off, and in the admin interface and other date/times on my website are all 7 hours off, even though settings.TIME_ZONE reports Africa/Johannesburg.

this code used to work, but at some point recently stopped working. I did change from pytz to zoneinfo, so that might be the reason, but I was a little bit sure it worked after the change.

Why is the timezone changing? How can I add a date/time format so it can be used in templates and in code with the django.utils.formats.date_format function?

run_the_race
  • 1,344
  • 2
  • 36
  • 62
  • What is globals() in this case? It looks like you are passing it to set_formats as a function when you might want to evaluate the function, return the result to a variable and then pass the variable instead. – SamSparx Jul 28 '22 at 00:21
  • @SamSparx globals() returns the global variables of a module as a dict, its a python builtin function – run_the_race Jul 28 '22 at 07:17
  • It's hard to emulate, but you might try globals() = my_dict, set_formats(my_dict) instead. – SamSparx Jul 28 '22 at 07:57
  • @SamSparx I don't think you understand how `globals()` works, please see https://docs.python.org/3/library/functions.html#globals – run_the_race Jul 28 '22 at 08:19
  • You're right, sorry. Didn't read your reply closely enough and ended up barking up entirely the wrong tree. – SamSparx Jul 28 '22 at 12:19

0 Answers0