-2

I have the following string representing a UTC timestamp: 2017-12-03T20:38:00.971261Z

I would like to convert it into Posix timestamp (IE: seconds since the epoch) Using this online converter (https://www.epochconverter.com/) I know the answer is 1512333480

But when I do the following code, the result is off by 1800 seconds -- 30 minutes:

>>> temp_time1 = datetime.datetime.strptime('2017-12-03T20:38:00.971261Z', '%Y-%m-%dT%H:%M:%S.%fZ')
>>> ctime = int(datetime.datetime(temp_time1.year,
                                  temp_time1.month,
                                  temp_time1.day,
                                  temp_time1.hour,
                                  temp_time1.minute,
                                  temp_time1.second,
                                  temp_time1.microsecond,
                                  pytz.timezone('Europe/London')).strftime('%s'))
>>> print ctime
1512351480

Anyone know what I'm missing here??

Saqib Ali
  • 11,931
  • 41
  • 133
  • 272

1 Answers1

5

You created a new timestamp and put it in the Europe/London timezone. That is not the same thing as UTC. The Europe/London timezone from the PyTZ database includes historical offsets, and those affect how datetime.datetime() interprets the timezone.

Just use the datetime.timestamp() method on the datetime object you already parsed from the string:

>>> import datetime
>>> temp_time1 = datetime.datetime.strptime('2017-12-03T20:38:00.971261Z', '%Y-%m-%dT%H:%M:%S.%fZ')
>>> temp_time1.timestamp()
1512333480.971261

Your original temp_time1 datetime object is timezone agnostic, so the timestamp() object already assumes no timezone conversion has to take place.

If you must apply the Europe/London timezone first for whatever reason, then at least use the timezone.localize() method to get the right offset applied:

>>> import pytz
>>> pytz.timezone('Europe/London').localize(temp_time1)
datetime.datetime(2017, 12, 3, 20, 38, 0, 971261, tzinfo=<DstTzInfo 'Europe/London' GMT0:00:00 STD>)
>>> pytz.timezone('Europe/London').localize(temp_time1).timestamp()
1512333480.971261

See How to make an unaware datetime timezone aware in python

For Python 2 and Python 3.0, 3.1 or 3.2, where datetime.timestamp() is not available, subtract the epoch date:

>>> (temp_time1 - datetime.datetime(1970, 1, 1)).total_seconds()
1512333480.971261

Add in the UTC timezone when dealing with timezone-aware datetime instances:

>>> (pytz.timezone('Europe/London').localize(temp_time1) - datetime.datetime(1970, 1, 1, tzinfo=pytz.utc)).total_seconds()
1512333480.971261

Combined into a function:

def datetime_to_timestamp(dt, epoch=datetime.datetime(1970, 1, 1)):
    if dt.tzinfo is not None:
        epoch = pytz.utc.localize(epoch)
    return (dt - epoch).total_seconds()
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343