datetime to Unix timestamp with millisecond precision
Question:
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?
Answers:
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.
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()
long((time.time() + 0.5) * 1000)
this has millisecond precision
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
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.
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
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
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?
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.
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()
long((time.time() + 0.5) * 1000)
this has millisecond precision
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
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.
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
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 thedatetime
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