40

I'm trying to do something really simple, convert a datetime object three days into the future into a Unix UTC timestamp:

import datetime, time
then = datetime.datetime.now() + datetime.timedelta(days=3)
# Method 1
print then.strftime("%s")
# Method 2
print time.mktime(then.timetuple())
# Method 3 
print time.mktime(then.timetuple()) * 1000

Method 1 and 2 give me Unix time in seconds, not milliseconds, and method 3 gives me milliseconds with no actual millisecond precision.

When I simply print then, I get datetime.datetime(2011, 11, 19, 15, 16, 8, 278271), so I know that the precision is available for milliseconds. How can I get a Unix timestamp with actual millisecond precision? If it's returned as a float and I have to flatten it to an an int, that's fine. Is there a solution I'm looking for that does this?

1

7 Answers 7

49

Datetime objects have a field named microsecond. So one way to achieve what you need is:

time.mktime(then.timetuple())*1e3 + then.microsecond/1e3

This returns milliseconds since UNIX epoch with the required precision.

Sign up to request clarification or add additional context in comments.

6 Comments

You're missing the punchline: print time.mktime(then.timetuple()) * 1000 + then.microsecond/1000
Nice solution, especially the ultra-hacker saving of one character by using 1e3 instead of 1000.
Naftuli, not really since 1e3 involves 3 distinct characters (1,e,3), and 1000 uses only 2 (1 and 0)
Maybe I'm missing something, but microseconds are millions of a second not thousandths. Also, I don't know why you multiply then divide. time.mktime(then.timetuple()) + then.microsecond/1e6 works for me.
@TheHerk I am not sure, but I think he wants the result in milliseconds. Your solution gives seconds, with milliseconds as decimal places.
|
28

In Python 3.3 and above, which support the datetime.timestamp() method, you can do this:

from datetime import datetime, timezone, timedelta

(datetime.now(timezone.utc) + timedelta(days=3)).timestamp() * 1e3

2 Comments

This should be the accepted answer.
My measurement shows that using timestamp() is also a lot faster than the solution by Adam Zalcman.
10

Assuming someone is interested in UTC, the following in valid after Python 3.3:

from datetime import datetime

now = int(datetime.utcnow().timestamp()*1e3)

Python 3.3 release notes:

New datetime.datetime.timestamp() method: Return POSIX timestamp corresponding to the datetime instance.

Intermediate results:

In [1]: datetime.utcnow().timestamp()
Out[1]: 1582562542.407362

In [2]: datetime.utcnow().timestamp()*1e3
Out[2]: 1582562566701.329

In [3]: int(datetime.utcnow().timestamp()*1e3)
Out[3]: 1582562577296

3 Comments

Be aware: This is only correct when the local timezone is UTC. datetime.utcnow() returns a naive timestamp (!). When calling method .timestamp() on it, it is assumed to be local timezone - which gives the wrong POSIX timestamp.
Thanks @HåkonT.! I will link the explanation coming from this SO answer: stackoverflow.com/questions/28573873/…
Using Python 3.12.3, I get a deprecation warning using this answer. The suggested answer is importing UTC from datetime and using datetime.now(UTC) instead of datetime.utcnow(). I.e. from datetime import datetime, UTC and then now = int(datetime.now(UTC).timestamp()*1e3)
4
long((time.time() + 0.5) * 1000)

this has millisecond precision

1 Comment

what it I have to get timestamp upto 7 decimal places something like this:1469172167.3014405
4

Day is always 86400 seconds in POSIX time. To get POSIX timestamp 3 days into the future as a float (with fraction of a second):

import time

DAY = 86400 # seconds
future = time.time() + 3 * DAY

It assumes that time.gmtime(0) is 1970 (POSIX Epoch).

If you already have a naive datetime object that represents time in the local timezone then the timestamp may be ambiguous during DST transitions. To avoid ambiguity, you could use a timezone aware datetime object or a naive datetime object that represents time in UTC.

To convert a local datetime dt to seconds since the Epoch:

from datetime import datetime
from time import mktime

timestamp = dt.timestamp() # Python 3.3+
timestamp = mktime(dt.timetuple()) + dt.microsecond / 1e6 # Python 2.7

It may fail if the local timezone had different utc offset in the past and the time implementation has no access to timezone database on the system. Use pytz to handle such cases.

To convert UTC datetime utc_dt to POSIX timestamp:

timestamp = (utc_dt - datetime(1970, 1, 1)).total_seconds()

To get milliseconds, just multiply any of the float number of seconds by 1e3.

1 Comment

Thanks! Note, should be dt.microsecond, not dt.microseconds
2

If sticking with datetimes in UTC, you can keep with that abstraction and leverage timedelta:

from datetime import datetime, timedelta

epoch = datetime.utcfromtimestamp(0)

def dt_from_ms(ms):
    return datetime.utcfromtimestamp(ms / 1000.0)

def dt_to_ms(dt):
    delta = dt - epoch
    return int(delta.total_seconds() * 1000)

then:

now = datetime.utcnow()
now
-> datetime.datetime(2017, 1, 25, 1, 30, 42, 765846)  # note microsecond precision

dt_to_ms(now)
-> 1485307842765

dt_from_ms(1485307842765)
-> datetime.datetime(2017, 1, 25, 1, 30, 42, 765000)  # note millisecond precision

then = now + timedelta(days=3)
dt_to_ms(then)
-> 1485567042765

(1485567042765 - 1485307842765) / (24*60*60*1000.0)
-> 3.0

Comments

0

If you are using Python 2.7 or 3.2+, you can use timedelta.total_seconds() to get this fairly easily:

import datetime, time
print time.time() + datetime.timedelta(days=3).total_seconds()

2 Comments

Why time delta?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.