В чем смысл наивного datetime

#python

#python

Вопрос:

Исходя из C #, я научился всегда учитывать часовые пояса при обработке даты / времени. Python имеет правильную обработку часовых поясов и полезные помощники, такие как datetime.utcnow, что упрощает работу с датой / временем. Но, читая в документах python, я заметил, что есть нечто, называемое «наивным» экземпляром datetime. Насколько я вижу, это просто datetime без какого-либо часового пояса.

Каков вариант использования наивного datetime? Разве datetime без часового пояса не бесполезен? И почему datetime.now() не возвращает datetime в текущей локали (например, .NET)?

Я уверен, что мне не хватает чего-то важного, поэтому я надеюсь, что кто-нибудь сможет пролить некоторый свет на это.

Ответ №1:

В чем смысл наивного datetime

Наивный datetime очень полезен!

В некоторых случаях вы не знаете или не хотите указывать часовой пояс.

Представьте, что вы анализируете древний файл журнала внешней программы и не знаете, в каком часовом поясе находятся даты и времени — лучше всего оставить их как есть. Привязка часового пояса к таким датам времени была бы неправильной и могла привести к ошибкам, поскольку вы бы притворялись, что у вас есть информация, которой у вас на самом деле нет.


И почему datetime.now() не возвращает datetime в текущей локали (например, .NET)?

datetime.now() возвращает значение в текущем часовом поясе locale, но с ним не связан часовой пояс ( tzinfo атрибут), что, вероятно, вы и имели в виду. Обратите внимание, что то же самое верно для utcnow() , оба возвращают наивные datetimes

Обоснование отсутствия поддержки часовых поясов в datetime модуле упоминается в документах:

Обратите внимание, что модуль datetime не предоставляет никаких конкретных классов tzinfo. […] Правила корректировки времени во всем мире скорее политические, чем рациональные, и не существует стандарта, подходящего для каждого приложения.

где -то, если вы включили поддержку часовых поясов в стандартную библиотеку, вы получите неправильные результаты в мире.

Часовые пояса — это политическая концепция, которая меняется несколько раз в год по всему миру. Ожидаемая продолжительность жизни локально установленной стандартной библиотеки python (как правило) намного больше, чем корректность данных часового пояса.


Что я должен сделать для поддержки часовых поясов

Отказ от ответственности: вы должны просто использовать UTC почти во всех случаях. Локальные часовые пояса следует использовать только в качестве последнего шага при отображении значений пользователю.

Чтобы использовать часовые пояса, ваша программа должна зависеть от pytz пакета, который дает вам надлежащую поддержку часового пояса.

 from time import tzname
from pytz import timezone
from datetime import datetime
timezone(tzname[0]).localize(datetime.now())
  

Помните, что вашей программе или локальному системному администратору необходимо будет обновлять пакет.

Ответ №2:

Каков вариант использования наивного datetime?

Python не выделяет пространство для указателя на объект timezone, если объект datetime является наивным:

 /* ---------------------------------------------------------------------------
 * Basic object allocation:  tp_alloc implementations.  These allocate
 * Python objects of the right size and type, and do the Python object-
 * initialization bit.  If there's not enough memory, they return NULL after
 * setting MemoryError.  All data members remain uninitialized trash.
 *
 * We abuse the tp_alloc "nitems" argument to communicate whether a tzinfo
 * member is needed.  This is ugly, imprecise, and possibly insecure.
 * tp_basicsize for the time and datetime types is set to the size of the
 * struct that has room for the tzinfo member, so subclasses in Python will
 * allocate enough space for a tzinfo member whether or not one is actually
 * needed.  That's the "ugly and imprecise" parts.  The "possibly insecure"
 * part is that PyType_GenericAlloc() (which subclasses in Python end up
 * using) just happens today to effectively ignore the nitems argument
 * when tp_itemsize is 0, which it is for these type objects.  If that
 * changes, perhaps the callers of tp_alloc slots in this file should
 * be changed to force a 0 nitems argument unless the type being allocated
 * is a base type implemented in this file (so that tp_alloc is time_alloc
 * or datetime_alloc below, which know about the nitems abuse).
 */

static PyObject *
time_alloc(PyTypeObject *type, Py_ssize_t aware)
{
    PyObject *self;

    self = (PyObject *)
        PyObject_MALLOC(aware ?
                        sizeof(PyDateTime_Time) :
                sizeof(_PyDateTime_BaseTime));
    if (self == NULL)
        return (PyObject *)PyErr_NoMemory();
    PyObject_INIT(self, type);
    return self;
}
  

Как вы используете наивные объекты datetime, зависит от вас. В моем коде я использую наивные объекты datatime как:

  1. Как если бы с ними был связан часовой пояс UTC, или
  2. Мне все равно, какой часовой пояс вообще.