#django #django-models #django-timezone
#django #django-модели #django-часовой пояс
Вопрос:
У меня есть этот код, который ведет себя довольно странно и открывает вопрос, как мне следует обращаться с часовыми поясами? Итак, сначала у меня есть объект datetime, который я создаю на основе информации, которую публикует пользователь:
time_zone = request.POST.get("time_zone")
date_start = request.POST.get("date_start")
time_day = request.POST.get("time_day")
time_zone_obj = pytz.timezone("Etc/" time_zone) # GMT 2 in this example
date_start = datetime.strptime(date_start, "%d/%m/%Y")
date_start = date_start.replace(tzinfo=time_zone_obj)
time_day = datetime.strptime(time_day, "%I:%M %p")
date_start = date_start.replace(hour=time_day.hour, minute=time_day.minute)
...
event.date_start = date_start
event.save()
print("event.date_start.hour:%s" % event.date_start.hour)
print("event.date_start.tzinfo:%s" % event.date_start.tzinfo)
print("is_aware(event.date_start:%s)" % is_aware(event.date_start))
return redirect("event_detail", event_id=event.id)
Это печатает event.date_start.hour:6
, event.date_start.tzinfo:Etc/GMT 2
и is_aware:True
. Затем, сразу после сохранения объекта и печати часа, он перенаправляется на event_detail
представление, очень просто:
def event_detail(request, event_id):
event = get_object_or_404(Event, id=event_id)
print("event.date_start.hour:%s" % event.date_start.hour)
print("event.date_start.tzinfo:%s" % event.date_start.tzinfo)
...
И он печатает event.date_start.hour:8
и event.date_start.tzinfo:UTC
. (он заменил информацию о tz на UTC) Я не понимаю, почему. Я сохраняю объект с четким tz_info. Пожалуйста, обратите внимание, что я напечатал час после сохранения объекта, а затем после его извлечения в другом представлении. Разница в два часа должна иметь какое-то отношение к часовому поясу, выбранному пользователем (GMT 2). Почему это так? Какой лучший способ сохранить эти данные?
Пользователь отправляет «6:00 утра» «GMT 2» в форме, а затем позже, когда я хочу показать время в HTML-описании события ( {{ event.date_start|date:"h:i A" }}
), отображается «8:00 утра».
Комментарии:
1. Обязательно ознакомьтесь с документацией о часовых поясах Django.
2. @KevinChristopherHenry прочитал это. Отредактировал вопрос, запустил щедрость.
Ответ №1:
Я предполагаю, что вы используете PostgreSQL для сохранения метки времени с учетом часового пояса.
Важно понимать, что (вопреки названию и распространенному мнению) PostgreSQL не сохраняет часовой пояс метки времени, учитывающей часовой пояс. Это просто способ сообщить PostgreSQL, что значение не соответствует некоторому местному времени, но известно о часовом поясе.
Затем PostgreSQL преобразует его в UTC и сохраняет как таковой. Если исходный часовой пояс важен, вам нужно сохранить его отдельно.
Дополнительная информация по теме: https://www.postgresqltutorial.com/postgresql-timestamp /
Лучший способ сохранить эти данные — отдельный столбец (обычно называемый timezone
). Я использую https://pypi.org/project/django-timezone-field /
Затем либо activate
часовой пояс (https://docs.djangoproject.com/en/3.1/ref/utils/#django.utils.timezone.activate ) или использовать localtime
(https://docs.djangoproject.com/en/3.1/ref/utils/#django.utils.timezone .localtime) функция util.
Ответ №2:
Согласно документам Django,
«Когда включена поддержка часовых поясов, Django сохраняет информацию о дате и времени в UTC в базе данных. По-прежнему рекомендуется хранить данные в UTC в вашей базе данных. Основная причина — переход на летнее время (DST). «
Итак, сохранение даты и времени в формате UTC в базе данных, как и ожидалось.
Теперь перейдем к вашему требованию. Чтобы отобразить время обратно в часовом поясе, который использовался для сохранения, вам необходимо добавить столбец в БД для хранения информации о часовом поясе.
При получении даты и времени преобразуйте ее обратно в требуемый часовой пояс, используя tzinfo, хранящийся в БД.
Это правильный способ сделать. Надеюсь, это поможет вам лучше понять.