zeebonk
zeebonk

Reputation: 5034

What is the point of a naive datetime

Coming from C#, I've learned to always be aware of time-zones when handling date/time. Python has proper timezone handling and useful helpers like datetime.utcnow, which makes working with date/time straight forward. But, when reading in the python docs, I noticed that there is something called a "naive" datetime instance. As far as I can see, this is just a datetime without any timezone.

What is the use-case for a naive datetime? Isn't a datetime without a time-zone pretty useless? And why doesn't datetime.now() return a datetime in the current locale (like .NET)?

I'm sure I'm missing something crucial, so I hope someone can shed some light on this.

Upvotes: 8

Views: 9996

Answers (2)

loopbackbee
loopbackbee

Reputation: 23322

What is the point of a naive datetime

A naive datetime is very useful!

In some cases you don't know or don't want to specify a timezone.

Imagine that you are parsing an ancient external program log file, and you don't know what timezone the datetimes are in - your best bet is leave them as-is. Attaching a timezone to such datetimes would be wrong and could lead to errors, as you'd be pretending to have information you don't actually have.


And why doesn't datetime.now() return a datetime in the current locale (like .NET)?

datetime.now() does return a value in the current locale timezone, but it doesn't have a timezone associated with it (a tzinfo attribute), which is probably what you meant. Notice that the same is true for utcnow(), both return naive datetimes

The rationale for not including timezone support in the datetime module is alluded to in the docs:

Note that no concrete tzinfo classes are supplied by the datetime module. [...] The rules for time adjustment across the world are more political than rational, and there is no standard suitable for every application.

If you included timezone support in the standard library, you'd get wrong results somewhere in the world.

Timezones are a political concept and change several times a year, globally. The life expectancy of the locally installed python standard library is (generally) much larger than the correctness of timezone data.


What should I do to support timezones

Disclaimer: you should just use UTC in almost all cases. Local timezones should only be used as a last step when showing values to the user.

To use timezones, your program should depend on the pytz package, which gives you proper timezone suport.

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

Remember that your program or the local system administrator will need to keep the package up to date.

Upvotes: 15

Maxim Egorushkin
Maxim Egorushkin

Reputation: 136247

What is the use-case for a naive datetime?

Python does not allocate space for the pointer to the timezone object if the datetime object is naive:

/* ---------------------------------------------------------------------------
 * 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;
}

How you use naive datetime objects is up to you. In my code I use naive datatime objects as:

  1. As if they had UTC timezone associated with them, or
  2. I don't care what the timezone is at all.

Upvotes: 1

Related Questions