Skip to content

Instantly share code, notes, and snippets.

@mcdonc
Created June 16, 2014 19:01
Show Gist options
  • Save mcdonc/90b3df9a51c35269ded6 to your computer and use it in GitHub Desktop.
Save mcdonc/90b3df9a51c35269ded6 to your computer and use it in GitHub Desktop.
>>> import pytz
>>> eastern = pytz.timezone('US/Eastern')
>>> import datetime
>>> now = datetime.datetime.now().replace(tzinfo=eastern)
>>> now.strftime('%a, %d %b %Y %H:%M:%S %z')
'Mon, 16 Jun 2014 15:01:02 -0456'
456. 456. What the fuck.
@dairiki
Copy link

dairiki commented Jun 16, 2014

Yeah, I just ran into this a few days ago (right after updating to pytz==2014.4). Seems like a bug to me, but it is documented that one should, instead of

    now = datetime.datetime.now().replace(tzinfo=eastern)

do

    now = datetime.datetime.now().localize(eastern)

@Ignas
Copy link

Ignas commented Jun 17, 2014

@tholo while your code is correct in terms of localize usage, it is incorrect in terms of the way "now" is being used. Unless machine this code is running is set to US/Eastern this code will always be wrong:

 >>> datetime.datetime.now(tz=pytz.timezone('US/Eastern')) # Correct
 datetime.datetime(2014, 6, 17, 3, 33, 49, 717505, tzinfo=<DstTzInfo 'US/Eastern' EDT-1 day, 20:00:00 DST>)
 >>> pytz.timezone('US/Eastern').localize(datetime.datetime.now()) # Wrong
 datetime.datetime(2014, 6, 17, 11, 0, 33, 256509, tzinfo=<DstTzInfo 'US/Eastern' EDT-1 day, 20:00:00 DST>)

And even on a machine that has it's timezone set to US/Eastern using now + localize will produce wrong timestamp for 1 hour a year (notice 1 hour 1 minute difference between 2 timestamps that would be produced by datetime.datetime.now() withing 1 minute):

  >>> pytz.timezone('US/Eastern').localize(datetime.datetime(2014, 11, 2, 1, 00, 0))
  ... - pytz.timezone('US/Eastern').localize(datetime.datetime(2014, 11, 2, 0, 59, 0))
  datetime.timedelta(0, 3660)

This is because pytz treats ambiguous timestamps as non-dst due to is_dst being false by default in localize:

  >>> (pytz.timezone('US/Eastern').localize(datetime.datetime(2014, 11, 2, 1, 00, 0), is_dst=True)
  ... - pytz.timezone('US/Eastern').localize(datetime.datetime(2014, 11, 2, 0, 59, 0)))
  datetime.timedelta(0, 60)

and datetime.datetime.now() produces naive datetime objects so it does not provide dst/non dst hints.

You can force pytz to raise errors on ambiguous/non-existent timestamps in case you are dealing with user input and want to handle it:

>>> pytz.timezone('US/Eastern').localize(datetime.datetime(2014, 11, 2, 1, 00, 0), is_dst=None)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/ignas/Uber/api/env/lib/python2.7/site-packages/pytz/tzinfo.py", line 349, in localize
    raise AmbiguousTimeError(dt)
pytz.exceptions.AmbiguousTimeError: 2014-11-02 01:00:00

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment