user1179299
user1179299

Reputation: 376

Python datetime to epoch

t='20180515102500'
d=datetime.strptime(t, "%Y%m%d%H%M%S")
millis_since_epoch = int(time.mktime(d.timetuple())) * 1000
print(millis_since_epoch)

gives me: 1526379900000 on repl.it(python 3.6.1) and on my local: 1526397900000 (python 2.7.14)

Why? What is the recommended way to convert datetime object to epoch?

Upvotes: 13

Views: 29431

Answers (4)

Neetin
Neetin

Reputation: 9

t = datetime.strptime(gr_dt_string, "%Y-%m-%dT%H:%M:%S")
if six.PY2:
    gr_mili = int((t - datetime.fromtimestamp(0)).total_seconds()) * 1000
else:
    gr_mili = int(t.timestamp() * 1000)

Upvotes: 0

abarnert
abarnert

Reputation: 365915

Your problem is that you're using naive datetime (and struct_tm and so on) objects. So you're asking how far 15 May 2018 10:25:00 in "whatever the local timezone on this machine is" is from the Unix epoch. If you run it on two machines with timezones 5 hours apart, you will get results that are 5*3600*1000 milliseconds apart.

The recommended way to do it is either:

d.timestamp() # returns difference from epoch as float seconds

… or:

d - datetime.fromtimestamp(0) # returns difference as timedelta

(It should be obvious how to convert either of those to float millis, or whatever else you need.)

But neither of those will make any difference here, since you're still using naive datetime objects. (At least you aren't mixing in other types from the time module and throwing away precision, but you're not solving your problem.)


The solution to your problem depends on what you're trying to do. Are these UTC timestamps? Are they timestamps in some known timezone that you know out-of-band?

If everything is UTC, the best thing to do is to explicitly create UTC objects, but the simplest thing to do (especially if you need your code to run in 2.7) is:

d - datetime.utcfromtimestamp(0)

This gives you a naive datetime representing 0 UTC seconds since the epoch, and subtracts it from your naive datetime representing X UTC seconds since the epoch, so you get a timedelta representing X seconds (specifically, 17666 days, 37500 seconds), without regard to what timezone the system is using.

Or, the smallest change to your existing code is to use utctimetuple instead of timetuple, which does the same thing in a more convoluted way.

Upvotes: 14

Shelef
Shelef

Reputation: 668

in python 3.6:

datetime.timestamp()

for example:

import datetime

timestamp = datetime.datetime.now().timestamp()

Upvotes: 8

IAmGroot
IAmGroot

Reputation: 91

Try this:

t='20180515102500'
d=datetime.datetime.strptime(t, "%Y%m%d%H%M%S")
print(d)
epoch = datetime.datetime.utcfromtimestamp(0)


def unix_time_millis(dt):
  return (dt - epoch).total_seconds() * 1000

unix_time_millis(d)

Let me know if that helps!

Upvotes: 6

Related Questions