-1

I just stumbled over

>>> a = datetime.datetime(2017, 12, 24)
>>> b = datetime.datetime(2017, 12, 24, tzinfo=datetime.timezone.utc)
>>> a - b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't subtract offset-naive and offset-aware datetimes

Now I wonder: Why don't have all datetime objects a timezone? Is a timezone more than an offset from UTC (+ an associated name)?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Martin Thoma
  • 124,992
  • 159
  • 614
  • 958
  • 3
    Because if you do not provide it, it is unknown... – Willem Van Onsem Jan 27 '18 at 18:07
  • 1
    Because not all datetime problems need to carry a timezone, and including one complicates matters? – Martijn Pieters Jan 27 '18 at 18:08
  • 1
    I can't answer on the design of `datetime`, but I suggest you look at this [comprehensive question and answer](https://stackoverflow.com/questions/7065164/how-to-make-an-unaware-datetime-timezone-aware-in-python) for tips on how to deal with timezones. – jpp Jan 27 '18 at 18:09
  • @WillemVanOnsem `from tzlocal import get_localzone; tz = get_localzone()` is able to get it. – Martin Thoma Jan 27 '18 at 18:12
  • @MartijnPieters Is there more about the timezone than the offset? If no, then one can easily get to the "non-timezone situation" by subtracting the offset, can't one? But not storing the timezone could mean that one does not know at which time exactly something happened. – Martin Thoma Jan 27 '18 at 18:25
  • 1
    @MartinThoma: yes, daylight savings time transitions, and historical timezone information; timezones are not static, if you have a date in the past, then the timezone could well be using a different offset. – Martijn Pieters Jan 27 '18 at 18:27
  • @MartinThoma Being able to get the local timezone doesn't necessarily help matters. For example, say you were parsing a bunch of log files and extracting datetime info, the local timezone on the machine running the code might not be the same as the one the logs came from. So encoding those datetime objs with timezone doesn't really make sense. – xgord Jan 27 '18 at 18:29
  • @MartijnPieters Ok, then let me rephrase my question: If you are given the offset, then things are simple, right? I mean the offset already includes DST and it doesn't care about timezones being static or not. Doesn't the OS give the offset (or how does `date +%z` give it?) – Martin Thoma Jan 27 '18 at 18:41
  • 1
    @MartinThoma: yes, a simple offset-only timezone doesn't include daylight savings transitions or historical information. No, the OS doesn't supply a simple offset. See the [Olson timezone database](https://en.wikipedia.org/wiki/Tz_database) for what kind of info the OS provides these days. – Martijn Pieters Jan 27 '18 at 18:55

1 Answers1

2

Because timezones are non-trivial and not just simple offsets, and not all use cases need to take timezones into account.

Not simple offsets

A timezone usually is not just an offset from UTC. Timezones may also dictate daylight savings time (when exactly does a timezone switch between summer and winter time), for example.

Not all use-cases need to handle DST, and sometimes you have string representations of datetime values that only include an offset from UTC. But that doesn't mean that you can assume that timezone handling in general only has to deal with an offset.

Timezones are not static entities

Timezones also change over time; what physical locations use what exact timezone can change, as well as the rules of a timezone. Because the Earth is a large place, this happens more often than you think. And not only can DST rules or geographical reach change, but so can the timezone offset. See Jon Skeet's highest voted answer for an example of a historical timezone change, where the database entries have been corrected over time as well.

Such changes certainly take place more often than Python releases can be made. As such, Python can't ship a comprehensive timezone database with the standard library and hope it'll stay up to date until the next release. Instead, the Python maintainers rely on third-party libraries to produce such a database; such libraries can follow a much more aggressive release cycle.

Not all use cases need timezones

However, many use cases involving datetime calculations do not need to include a timezone; they can and should be timezone agnostic. Forcing all such use cases to use a timezone anyway would put an undue burden on developers that then have to understand how to handle calculations with other datetime values that do include timezone information.

So, the datetime library distinguishes between 'simple' datetime values without a timezone, and those with a timezone. Until Python 3.2, the library didn't even include a timezone object; that was left to third-party libraries. The current datetime.timezone() support is there to support simple offset timezones without history or DST support; those at least don't require constant maintenance and updates.

If you need access to proper timezones

The canonical Python implementation for timezones is the pytz package, which packages the Olson database (used by UNIX-like OSes including Mac OS X). A new release is created whenever the Olson database is updated; I'd expect a new 2018-01 release to package the recent 2018c release.

Do take into account that the datetime library design didn't anticipate having to handle historical timezone changes that pytz includes with a timezone; do follow the pytz documentation and use timezone.localize(naive_datetime) to apply the correct offsets for the date. See How to make an unaware datetime timezone aware in python

The python-dateutil package also contains timezone support.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343