2

I have a timestamp that represents milliseconds since 1970 1432202088224 which translates to Thursday, May 21, 2015 5:54:48 AM EDT. I'd like to write a python function that converts that timestamp to milliseconds in GMT. I can't naively add four hours (3600000 milliseconds) to the existing timestamp because half the year i'll be off by one hour.

I've tried writing a function using datetime and pytz

def convert_mills_GMT(milliseconds):
    converted_raw = datetime.datetime.fromtimestamp(milliseconds/1000.0)
    date_eastern = eastern.localize(converted_raw, is_dst=True)
    date_utc = date_eastern.astimezone(utc)
    return int(date_utc.strftime("%s")) * 1000

using the input of 1432202088224 this function returns 1432220088000 which is Thursday, May 21, 2015 10:54:48 AM EDT when what I want is 9:54 AM. what am I missing?

idclark
  • 948
  • 1
  • 8
  • 27

2 Answers2

2

There is no such thing as "EST timestamp". If you need "GMT timestamp" then you already have it.

To get UTC time from a POSIX timestamp given as number of milliseconds:

>>> from datetime import datetime, timedelta
>>> timestamp = 1432202088224
>>> utc_time = datetime(1970, 1, 1) + timedelta(milliseconds=timestamp)
>>> utc_time.strftime('%A, %B %d, %Y %H:%M:%S %p UTC')
'Thursday, May 21, 2015 09:54:48 AM UTC'

We can check that the result is correct by converting the UTC time back to "EST" timezone:

>>> import pytz # $ pip install pytz
>>> est = utc_time.replace(tzinfo=pytz.utc).astimezone(pytz.timezone('US/Eastern'))
>>> est.strftime('%A, %B %d, %Y %H:%M:%S %p %Z')
'Thursday, May 21, 2015 05:54:48 AM EDT'
jfs
  • 399,953
  • 195
  • 994
  • 1,670
0

Don't use .strftime("%s"). It is not supported, and may silently fail. Instead, to convert a UTC datetime to a timestamp use one of the methods shown here depending on your version of Python:

Python 3.3+:

timestamp = dt.timestamp()

Python3 (< 3.3):

epoch = datetime(1970, 1, 1, tzinfo=timezone.utc)
timestamp = (dt - epoch) / timedelta(seconds=1)

Python 2.7+:

timestamp = (dt.replace(tzinfo=None) - datetime(1970, 1, 1)).total_seconds()

Python2 (< 2.7):

def totimestamp(dt, epoch=datetime(1970,1,1)):
    td = dt - epoch
    # return td.total_seconds()
    return (td.microseconds + (td.seconds + td.days * 86400) * 10**6) / 10**6 
timestamp = totimestamp(dt.replace(tzinfo=None))

Therefore, your convert_mills_GMT should look like

def convert_mills_GMT(milliseconds, 
                      utc=pytz.utc,
                      eastern=pytz.timezone('US/Eastern')
):
    converted_raw = DT.datetime.fromtimestamp(milliseconds/1000.0)
    date_eastern = eastern.localize(converted_raw, is_dst=True)
    date_utc = date_eastern.astimezone(utc)
    timestamp = ...
    return int(timestamp) * 1000

For example, with Python2.7,

import datetime as DT
import pytz

def convert_mills_GMT(milliseconds, 
                      utc=pytz.utc,
                      eastern=pytz.timezone('US/Eastern')
):
    converted_raw = DT.datetime.fromtimestamp(milliseconds/1000.0)
    date_eastern = eastern.localize(converted_raw, is_dst=True)
    date_utc = date_eastern.astimezone(utc)
    timestamp = ((date_utc.replace(tzinfo=None) - DT.datetime(1970, 1, 1))
                 .total_seconds())
    return int(timestamp) * 1000

print(DT.datetime.utcfromtimestamp(convert_mills_GMT(1432202088224)/1000.0))

prints

2015-05-21 09:54:48
Community
  • 1
  • 1
unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677