35

I'm trying to convert timezone aware datetime object to UTC and then back to it's original timezone. I have a following snippet

t = datetime(
    2013, 11, 22, hour=11, minute=0,
    tzinfo=pytz.timezone('Europe/Warsaw')
)

now in ipython:

In [18]: t
Out[18]: datetime.datetime(
    2013, 11, 22, 11, 0, tzinfo=<DstTzInfo 'Europe/Warsaw' WMT+1:24:00 STD>
)

and now let's try to do conversion to UTC and back. I would expect to have the same representation as:

In [19]: t.astimezone(pytz.utc).astimezone(pytz.timezone('Europe/Warsaw'))
Out[19]: datetime.datetime(
    2013, 11, 22, 10, 36, tzinfo=<DstTzInfo 'Europe/Warsaw' CET+1:00:00 STD>
)

Yet we see that Out[18] and Out[19] differ. What's going on?

yakxxx
  • 2,841
  • 2
  • 21
  • 22
  • 1
    Django stores datetimes naive database wise. If you handle that case, have a look here to convert dates to the timezone you need: https://docs.djangoproject.com/en/dev/topics/i18n/timezones/#usage – Jingo Aug 30 '13 at 21:06
  • whether Django stores naive datetimes of not is controlled by the `USE_TZ` setting. If that is `True` then Django treats datetimes in forms etc as being in the [current timezone](https://docs.djangoproject.com/en/dev/topics/i18n/timezones/#selecting-the-current-time-zone) and stores them in the db converted to UTC. – Anentropic Feb 18 '14 at 13:32
  • 2
    Could you specify the "mind blowing behaviour" further? I don't like clickbait on StackExchange – Martin Thoma Mar 14 '18 at 15:17

1 Answers1

71

The documentation http://pytz.sourceforge.net/ states "Unfortunately using the tzinfo argument of the standard datetime constructors 'does not work' with pytz for many timezones." The code:

t = datetime(
    2013, 5, 11, hour=11, minute=0,
    tzinfo=pytz.timezone('Europe/Warsaw')
)

doesn't work according to this, instead you should use the localize method:

t = pytz.timezone('Europe/Warsaw').localize(
        datetime(2013, 5, 11, hour=11, minute=0))
gsamaras
  • 71,951
  • 46
  • 188
  • 305
James K
  • 3,692
  • 1
  • 28
  • 36
  • 24
    Python datetime module assumes a timezone object has a constant UTC offset. Pytz timezone objects have varying UTC offsets (because daylight savings times as well as historical timezone changes). When you use pytz's localize() it can pick up the right offset for that particular date. When you use datetime's replace(tzinfo==) you end up with the oldest UTC offset for that timezone in the database. – Marius Gedminas Jun 17 '14 at 14:11