[issue22627] Calling timestamp() on a datetime object modifies the timestamp of a different datetime object.

Akira Li report at bugs.python.org
Wed Oct 15 04:07:28 CEST 2014


Akira Li added the comment:

Christopher, 

About your script http://paste.ubuntu.com/8562027/

dateutil may break if the local timezone had different UTC offset in the past.
You could  use tzlocal module to get pytz timezone that can handle such 
timezones. 

To get the correct time for 1414274400 timezone in Europe/Moscow timezone,
you need the latest tz database e.g., `pytz` works but fromtimestamp, dateutil
that use the local tz database fail (2:00 instead of 1:00):

  >>> import time
  >>> import os
  >>> os.environ['TZ'] = 'Europe/Moscow'
  >>> time.tzset()
  >>> from datetime import datetime, timezone
  >>> from tzlocal import get_localzone 
  >>> datetime.fromtimestamp(1414274400, get_localzone())
  datetime.datetime(2014, 10, 26, 1, 0, tzinfo=<DstTzInfo 'Europe/Moscow' MSK+3:00:00 STD>)
  >>> datetime.utcfromtimestamp(1414274400).replace(tzinfo=timezone.utc).astimezone(get_localzone())
  datetime.datetime(2014, 10, 26, 1, 0, tzinfo=<DstTzInfo 'Europe/Moscow' MSK+3:00:00 STD>)
  >>> datetime.fromtimestamp(1414274400) # wrong
  datetime.datetime(2014, 10, 26, 2, 0)
  >>> datetime.fromtimestamp(1414274400, timezone.utc).astimezone() # wrong
  datetime.datetime(2014, 10, 26, 2, 0, tzinfo=datetime.timezone(datetime.timedelta(0, 14400), 'MSK'))
  >>> datetime.utcfromtimestamp(1414274400).replace(tzinfo=timezone.utc).astimezone() # wrong
  datetime.datetime(2014, 10, 26, 2, 0, tzinfo=datetime.timezone(datetime.timedelta(0, 14400), 'MSK'))
  >>> from dateutil.tz import gettz, tzutc
  >>> datetime.fromtimestamp(1414274400, gettz()) # wrong
  datetime.datetime(2014, 10, 26, 2, 0, tzinfo=tzfile('/usr/share/zoneinfo/Europe/Moscow'))
  >>> datetime.fromtimestamp(1414274400, tzutc()).astimezone(gettz()) # wrong
  datetime.datetime(2014, 10, 26, 2, 0, tzinfo=tzfile('/usr/share/zoneinfo/Europe/Moscow'))
  >>> datetime.utcfromtimestamp(1414274400).replace(tzinfo=tzutc()).astimezone(gettz()) # wrong
  datetime.datetime(2014, 10, 26, 2, 0, tzinfo=tzfile('/usr/share/zoneinfo/Europe/Moscow'))


To avoid surprises, always use UTC time to perform date arithmetics:

  EPOCH = datetime(1970, 1,1, tzinfo=pytz.utc)
  utc_dt = EPOCH + timedelta(seconds=timestamp)

should work for dates after 2038 too.

To convert it to the local timezone:

  from tzlocal import get_localzone

  local_dt = utc_dt.astimezone(get_localzone())
  ts = (local_dt - EPOCH) // timedelta(seconds=1)
  assert ts == timestamp # if timestamp is an integer

Python stdlib assumes POSIX encoding for time.time() value (issue22356)  
therefore the formulae work on all platforms where Python works.

----------
nosy: +akira

_______________________________________
Python tracker <report at bugs.python.org>
<http://bugs.python.org/issue22627>
_______________________________________


More information about the Python-bugs-list mailing list