117

I have used a ruby script to convert iso time stamp to epoch, the files that I am parsing has following time stamp structure:

2009-03-08T00:27:31.807

Since I want to keep milliseconds I used following ruby code to convert it to epoch time:

irb(main):010:0> DateTime.parse('2009-03-08T00:27:31.807').strftime("%Q")
=> "1236472051807"

But In python I tried following:

import time 
time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(1236472051807))

But I don't get the original time date time back,

>>> time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(1236472051807))
'41152-03-29 02:50:07'
>>> 

I wonder is it related to how I am formatting?

martineau
  • 119,623
  • 25
  • 170
  • 301
add-semi-colons
  • 18,094
  • 55
  • 145
  • 232

3 Answers3

200

Use datetime.datetime.fromtimestamp:

>>> import datetime
>>> s = 1236472051807 / 1000.0
>>> datetime.datetime.fromtimestamp(s).strftime('%Y-%m-%d %H:%M:%S.%f')
'2009-03-08 09:27:31.807000'

%f directive is only supported by datetime.datetime.strftime, not by time.strftime.

UPDATE Alternative using %, str.format:

>>> import time
>>> s, ms = divmod(1236472051807, 1000)  # (1236472051, 807)
>>> '%s.%03d' % (time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(s)), ms)
'2009-03-08 00:27:31.807'
>>> '{}.{:03d}'.format(time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(s)), ms)
'2009-03-08 00:27:31.807'
falsetru
  • 357,413
  • 63
  • 732
  • 636
  • 3
    yeah I was gonna suggest this ... but meh good answer(+1 for preserving the milliseconds in the display :)) – Joran Beasley Feb 14 '14 at 19:18
  • Great answer also @JoranBeasley yours is great too :) Thanks guys. – add-semi-colons Feb 14 '14 at 19:49
  • 1
    Please note @falsetru first answer divide by floating point `1000.0` thus maintaining the milliseconds in the datetime. – Lorenzo Belli May 23 '17 at 14:35
  • Thanks. Exactly what I was looking for – anish Jan 22 '20 at 12:38
  • Note: `fromtimestamp` expects an int or a float. If you pass it a Decimal; its behaviour depends on your python version. Some python versions (<= 3.5?) will convert to a float and work as expected. While python 3.8 issues a warning and **converts to an int**, discarding any milliseconds your input may have provided. – Aaron Dec 07 '20 at 22:22
24

those are miliseconds, just divide them by 1000, since gmtime expects seconds ...

time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(1236472051807/1000.0))
Joran Beasley
  • 110,522
  • 12
  • 160
  • 179
3

I'm a pendulum fan... so...

import pendulum
pendulum.from_timestamp(1236472051807/1000.0,tz='America/Toronto')

outputs:

DateTime(2019, 12, 20, 10, 55, 10, tzinfo=Timezone('America/Toronto'))

For all the searches looking for internalDate for the Gmail API... the above is what works for me and is more accurate than the Date header.

rjmoggach
  • 1,458
  • 15
  • 27