473

I have a Python datetime object that I want to convert to unix time, or seconds/milliseconds since the 1970 epoch.

How do I do this?

Martin Thoma
  • 124,992
  • 159
  • 614
  • 958
SuperString
  • 21,593
  • 37
  • 91
  • 122
  • 3
    related: [Converting datetime.date to UTC timestamp in Python](http://stackoverflow.com/q/8777753/4279) – jfs Jan 27 '15 at 22:57
  • 1
    If you landed here just wanting _current_ epoch seconds with millisecond precision, try `$ python -c 'import time; print(time.time())'` which gave: `1584487455.698623` – MarkHu Mar 17 '20 at 23:27
  • @MarkHu that seems microseconds precision. – MrR Jul 01 '20 at 19:02

13 Answers13

560

It appears to me that the simplest way to do this is

import datetime

epoch = datetime.datetime.utcfromtimestamp(0)

def unix_time_millis(dt):
    return (dt - epoch).total_seconds() * 1000.0
Sophie Alpert
  • 139,698
  • 36
  • 220
  • 238
  • 35
    So far this is the best solution (if python version >2.7). Because the implementation of `%s` is OS dependent! Thus anyone want the code works reliably regardless on which OS, should NEVER use `%s`. For 2.3 < py ver <2.7. One can simply build a `total_seconds()` like this: `delta.days*86400+delta.seconds+delta.microseconds/1e6` – Wang Jul 24 '12 at 10:32
  • 14
    note: `dt` must be in UTC (not local). See [similar answer with Python 2.6/3 support](http://stackoverflow.com/a/8778548/4279) – jfs Oct 28 '12 at 19:50
  • 7
    Worth mentioning that if all you want is a true unix timestamp as defined here http://en.wikipedia.org/wiki/Unix_time (and so will only be using the unix_time function from this answer) then you should wrap delta.total_seconds() with int to avoid ending up with a float – corford Dec 30 '14 at 11:20
  • 1
    epoch calculated using `utcfromtimestamp(0)` may cause a 'tz' offset only if 'tz' is not 0. This is because `dt` in `dt- epoch` has 'tz' calculated in it where as epoch is UTC time. The best way to calculate epoch is `epoch = datetime.datetime(1970, 1, 1)` where timezone is in consideration. – ahj Jan 06 '16 at 15:31
  • The problem with this solution is it does not consider UTC time for "dt". In my opinion, everyone should always use UTC time. Best solution is by @estani below. – Sarang Jun 21 '16 at 12:38
  • 53
    Why oh why does `datetime.utcfromtimestamp(0)` return a datetime without tzinfo? It's right there in the method name, **utc**fromtimestamp. In order to make it non-naive I have to do something like `datetime.utcfromtimestamp(0).replace(tzinfo=pytz.UTC)`. This is necessary if `dt` is timezone aware or else you will get `TypeError: can't subtract offset-naive and offset-aware datetimes` – FGreg Sep 01 '16 at 18:03
  • @Wang did you mean `>= 2.7`? – Dan M. Aug 21 '18 at 12:40
  • This produces epochs in the form 1536236537522.0872. It is the correct time, but its decimal place needs to be 3 places higher so that its 1536236537.5220872. I used the above and my dt = datetime.datetime.utcnow(). – Daniel Cull Sep 06 '18 at 12:27
  • Nice. Suggestion, we should call it: Sophie Alpert Algorithm ;-) – adhg Jun 17 '20 at 16:34
  • Can someone explain why the epoch = datetime.datetime.utcfromtimestamp(0) is *outside* of the function itself? – user6400946 Jul 15 '21 at 08:19
301

In Python 3.3, added new method timestamp:

import datetime
seconds_since_epoch = datetime.datetime.now().timestamp()

Your question stated that you needed milliseconds, which you can get like this:

milliseconds_since_epoch = datetime.datetime.now().timestamp() * 1000

If you use timestamp on a naive datetime object, then it assumed that it is in the local timezone. Use timezone-aware datetime objects if this is not what you intend to happen.

Flimm
  • 136,138
  • 45
  • 251
  • 267
eshizhan
  • 4,235
  • 2
  • 23
  • 23
  • 46
    Note: `.timestamp()` method assumes that a naive input datetime is in the local timezone (and the local time may be ambiguous). If it is in UTC then use [`dt.replace(tzinfo=timezone.utc).timestamp()` instead](http://stackoverflow.com/a/8778548/4279). – jfs Dec 29 '14 at 01:12
  • 15
    datetime.timestamp() returns epoch seconds as a float. To obtain miliseconds: int(datetime.timestamp() * 1000) – Solar.gy Aug 02 '17 at 15:28
  • 11
    This answer is not a copy-and-pasteable example, in the spirit of the un-human-friendly docs at https://docs.python.org/3/library/datetime.html#datetime.datetime.timestamp --this is: `datetime.datetime.timestamp(datetime.datetime.now())` – MarkHu Feb 01 '18 at 20:01
  • 5
    In 3.6 (at least), datetime.timestamp() assumes a timezone naive (tzinfo=None) datetime is in UTC. So always better to have your timezone set: `datetime.datetime.now(pytz.timezone('Europe/Paris')).timestamp() == datetime.datetime.now(pytz.utc).timestamp() == datetime.datetime.utcnow().timestamp()` but not (always) equal to `datetime.datetime.now().timestamp()` (this last one is only equal to the rest if the local tz is UTC...) – bluu Jul 12 '18 at 14:28
  • 2
    For your interest, the reverse is ]`fromtimestamp`\(https://docs.python.org/3/library/datetime.html#datetime.datetime.fromtimestamp) – Flimm Mar 04 '20 at 14:12
  • in python 3.7 there is not timestamp() in datetime? – DennisLi Apr 30 '20 at 14:12
  • @DennisLi `timestamp()` is a method of the `datetime.datetime` class. – pabouk - Ukraine stay strong May 24 '22 at 22:29
107
>>> import datetime
>>> # replace datetime.datetime.now() with your datetime object
>>> int(datetime.datetime.now().strftime("%s")) * 1000 
1312908481000

Or the help of the time module (and without date formatting):

>>> import datetime, time
>>> # replace datetime.datetime.now() with your datetime object
>>> time.mktime(datetime.datetime.now().timetuple()) * 1000
1312908681000.0

Answered with help from: http://pleac.sourceforge.net/pleac_python/datesandtimes.html

Documentation:

miku
  • 181,842
  • 47
  • 306
  • 310
  • 6
    Btw, strftime("%s") returns an empty string for me. The second way works fine. – Pavel Vlasov Apr 06 '12 at 16:32
  • 25
    Only has second accuracy – shuckc Nov 22 '13 at 18:35
  • 6
    '%s' is not supported by Python e.g., it might be absent on Windows. `.timetuple()` returns `tm_isdst=-1` it forces `mktime()` to guess. It may guess wrongly during DST (50% chance of an error +/- hour). Both '%s' and `mktime()` may use the wrong utc offset for dates from the past. You need a historical timezone db such as provided by `pytz` module to reliably convert local time to POSIX timestamp (unless OS already provides such db) – jfs May 15 '14 at 19:01
  • 1
    `time.mktime(ts.timetuple())` where ts is python's datetime object – suhailvs Sep 22 '14 at 08:19
  • 1
    @suhail: read my comment above about `mktime/timetuple`. Also `timetuple()` strips fractions of a second and the point of the question is to get the timestamp with millisecond precision. – jfs Dec 29 '14 at 01:18
  • 1
    note: `.timetuple()` does not contains the time less than 1 second. – fx-kirin Feb 16 '15 at 15:00
  • 1
    disadvantage of using `%s`: https://stackoverflow.com/a/11743262/2383136 – S.K. Venkat Jan 16 '20 at 19:12
18

You can use Delorean to travel in space and time!

import datetime
import delorean
dt = datetime.datetime.utcnow()
delorean.Delorean(dt, timezone="UTC").epoch

http://delorean.readthedocs.org/en/latest/quickstart.html  

Etaoin
  • 149
  • 2
  • 7
working4coins
  • 1,997
  • 3
  • 22
  • 30
15

This is how I do it:

from datetime import datetime
from time import mktime

dt = datetime.now()
sec_since_epoch = mktime(dt.timetuple()) + dt.microsecond/1000000.0

millis_since_epoch = sec_since_epoch * 1000
estani
  • 24,254
  • 2
  • 93
  • 76
  • see [my comment about timetuple/mktime](http://stackoverflow.com/questions/6999726/how-can-i-convert-a-datetime-object-to-milliseconds-since-epoch-unix-time-in-p?answertab=votes#comment36393216_6999787) – jfs Dec 29 '14 at 01:16
  • 2
    @J.F.Sebastian Thanks for the heads up! indeed there is no dst being considered. If your server is in localtime instead of UTC then it will make a difference. I haven't found (yet) any compelling reason for setting servers in anything other than UTC. My moto is "write UTC, read local-time" so you know always where you are staying... – estani Jan 02 '15 at 16:04
  • 2
    You can always use calendar.timegm instead of mktime to avoid the issue of mktime trying to guess the timezone. – Decko Mar 30 '17 at 17:42
15

Recommendedations from the Python 2.7 docs for the time module

Converting between time representations

MarkHu
  • 1,694
  • 16
  • 29
Ankur Agarwal
  • 23,692
  • 41
  • 137
  • 208
  • @ChristopherBull Just divide the number of milliseconds by 1000 to get to seconds – Jonas Feb 01 '17 at 19:49
  • 6
    You misunderstood and got it the wrong way around. Seconds are all ready available in the above functions. You can convert it to milliseconds, but it would be the precision of a second. – Christopher Bull Feb 01 '17 at 19:57
  • 1
    This answer uses the `time` module, but the OP asked about `datetime` module. FWIW, the simplest current epoch is `int(time.time())` – MarkHu Feb 01 '18 at 19:38
11
from datetime import datetime
from calendar import timegm

# Note: if you pass in a naive dttm object it's assumed to already be in UTC
def unix_time(dttm=None):
    if dttm is None:
       dttm = datetime.utcnow()

    return timegm(dttm.utctimetuple())

print "Unix time now: %d" % unix_time()
print "Unix timestamp from an existing dttm: %d" % unix_time(datetime(2014, 12, 30, 12, 0))
corford
  • 985
  • 10
  • 12
  • `timegm()` works only with utc time. It doesn't use `tm_isdst` therefore you could use `utcnow.timetuple()` instead of `utcnow.utctimetuple()`. Note: using `naive_local_datetime.utctimetuple()` would be wrong here. It doesn't translate local time to utc. Also `timetuple()` call strips fractions of a second from the result (whether it matters depends on application). Also the question asks about *milli*​seconds, not seconds – jfs May 15 '14 at 18:52
  • I prefer to use utcnow() and utctimetuple() to make the code absolutely clear that you're dealing with UTC (and this way anyone reading it doesn't have to remember that timegm is UTC only). utctimetuple() doesn't imply translation on a naive dttm object (hence initing the dttm with utcnow() ). Also, question mentioned seconds or milliseconds. – corford May 17 '14 at 11:15
  • Note: should have said in last comment I read the question as implying he wanted seconds or milliseconds (probably my mistake). For millis just multiply by 1000 (as the top scoring answer suggests). – corford May 17 '14 at 11:23
  • `utctimetuple()` strips fractions of a second. Multiplying by `1000` won't get them back. – jfs Dec 29 '14 at 01:14
  • That's of course true. If you need real accuracy down to milliseconds then go with the top scoring answer. If you just want a simple unix timestamp (as defined here http://en.wikipedia.org/wiki/Unix_time) then either approach is valid. – corford Dec 30 '14 at 08:33
  • Are you suggesting that I close this question as a duplicate of [Change datetime to Unix time stamp in Python](http://stackoverflow.com/q/8542723/4279)? – jfs Dec 30 '14 at 09:41
  • 1
    Because of the way the OP asked this question, it's unclear exactly what he/she wanted (i.e. a true unix timestamp or a timestamp with millisecond accuracy). Regardless, both questions have already been asked and answered elsewhere. Having said that, I think the answers here are the quickest and cleanest for people to grok and do a nice job of illustrating the various solutions to the problem. – corford Dec 30 '14 at 11:07
4

Here's another form of a solution with normalization of your time object:

def to_unix_time(timestamp):
    epoch = datetime.datetime.utcfromtimestamp(0) # start of epoch time
    my_time = datetime.datetime.strptime(timestamp, "%Y/%m/%d %H:%M:%S.%f") # plugin your time object
    delta = my_time - epoch
    return delta.total_seconds() * 1000.0
arhoskins
  • 362
  • 2
  • 14
3
>>> import datetime
>>> import time
>>> import calendar

>>> #your datetime object
>>> now = datetime.datetime.now()
>>> now
datetime.datetime(2013, 3, 19, 13, 0, 9, 351812)

>>> #use datetime module's timetuple method to get a `time.struct_time` object.[1]
>>> tt = datetime.datetime.timetuple(now)
>>> tt
time.struct_time(tm_year=2013, tm_mon=3, tm_mday=19, tm_hour=13, tm_min=0, tm_sec=9,     tm_wday=1, tm_yday=78, tm_isdst=-1)

>>> #If your datetime object is in utc you do this way. [2](see the first table on docs)
>>> sec_epoch_utc = calendar.timegm(tt) * 1000
>>> sec_epoch_utc
1363698009

>>> #If your datetime object is in local timeformat you do this way
>>> sec_epoch_loc = time.mktime(tt) * 1000
>>> sec_epoch_loc
1363678209.0

[1] http://docs.python.org/2/library/datetime.html#datetime.date.timetuple

[2] http://docs.python.org/2/library/time.html

Jinesh
  • 2,507
  • 2
  • 22
  • 23
3

A bit of pandas code:

import pandas

def to_millis(dt):
    return int(pandas.to_datetime(dt).value / 1000000)
volhv
  • 1,167
  • 1
  • 12
  • 13
2

A lot of these answers don't work for python 2 or don't preserve the milliseconds from the datetime. This works for me

def datetime_to_ms_epoch(dt):
    microseconds = time.mktime(dt.timetuple()) * 1000000 + dt.microsecond
    return int(round(microseconds / float(1000)))
Daniel Kobe
  • 9,376
  • 15
  • 62
  • 109
  • This was the first answer that did what I needed—milliseconds since epoch, not just by multiplying seconds since epoch by 1,000. – Andrew Cheong Jan 01 '23 at 14:10
1

Here is a function I made based on the answer above

def getDateToEpoch(myDateTime):
    res = (datetime.datetime(myDateTime.year,myDateTime.month,myDateTime.day,myDateTime.hour,myDateTime.minute,myDateTime.second) - datetime.datetime(1970,1,1)).total_seconds()
    return res

You can wrap the returned value like this : str(int(res)) To return it without a decimal value to be used as string or just int (without the str)

Gil Allen
  • 1,169
  • 14
  • 24
1
import time
seconds_since_epoch = time.mktime(your_datetime.timetuple()) * 1000
MattoTodd
  • 14,467
  • 16
  • 59
  • 76
  • 10
    This is wrong! The timetuple does not include millisecond, thus mktime will not return the epoch with millisecond resolution. It is useless in this case. – Wang Jul 24 '12 at 09:19
  • @Wang - you are correct sir, this does not return millis, only seconds – MattoTodd Aug 20 '12 at 22:34
  • see [my comment about timetuple/mktime](http://stackoverflow.com/questions/6999726/how-can-i-convert-a-datetime-object-to-milliseconds-since-epoch-unix-time-in-p?answertab=votes#comment36393216_6999787) – jfs Dec 29 '14 at 01:10
  • 2
    If you remove `* 1000`, though, you do get `seconds_since_epoch`. Upvoting this answer because I don't care about milliseconds right now. – Michael Scheper Apr 27 '16 at 21:35