In Python, how do you convert seconds since epoch to a `datetime` object?
Asked Answered
S

6

352

The time module can be initialized using seconds since epoch:

import time
t1 = time.gmtime(1284286794)
t1
time.struct_time(tm_year=2010, tm_mon=9, tm_mday=12, tm_hour=10, tm_min=19, 
                 tm_sec=54, tm_wday=6, tm_yday=255, tm_isdst=0)

Is there an elegant way to initialize a datetime.datetime object in the same way?

Striation answered 12/9, 2010 at 10:28 Comment(1)
for the opposite operation go here: convert-a-datetime-object-to-secondsBounteous
I
548

datetime.datetime.fromtimestamp will do, if you know the time zone, you could produce the same output as with time.gmtime

>>> datetime.datetime.fromtimestamp(1284286794)
datetime.datetime(2010, 9, 12, 11, 19, 54)

or

>>> datetime.datetime.utcfromtimestamp(1284286794)
datetime.datetime(2010, 9, 12, 10, 19, 54)
Insusceptible answered 12/9, 2010 at 10:33 Comment(2)
bizarrely, datetime.utcfromtimestamp creates a naive timestamp. I had to import pytz and use datetime.fromtimestamp(1423524051, pytz.utc) to create an aware datetime.Damaging
as a follow-on to the above, with Python >= 3.2 you don't have to import the pytz library if you only want the UTC timestamp - you only need to from datetime import datetime, timezone and then call it as follows: datetime.fromtimestamp(1423524051, timezone.utc). It has saved the extra library many times when I only need the UTC timezone from pytz.Hyde
V
62

Seconds since epoch to datetime to strftime:

>>> ts_epoch = 1362301382
>>> ts = datetime.datetime.fromtimestamp(ts_epoch).strftime('%Y-%m-%d %H:%M:%S')
>>> ts
'2013-03-03 01:03:02'
Vitrescent answered 3/3, 2013 at 18:3 Comment(2)
It should be datetime.fromtimestamp(1579366345).strftime('%Y-%m-%d %H:%M:%S')Alack
@vml19, it depends on whether datetime was imported from datetime or not (import datetime vs. from datetime import datetime).Diggings
A
53

From the docs, the recommended way of getting a timezone aware datetime object from seconds since epoch is:

Python 3:

from datetime import datetime, timezone
datetime.fromtimestamp(timestamp, timezone.utc)

Python 2, using pytz:

from datetime import datetime
import pytz
datetime.fromtimestamp(timestamp, pytz.utc)
Alicea answered 8/1, 2016 at 4:48 Comment(3)
A link to the documentation in your subtitles ("Python 3", "Python 2") would be useful - and I also recommend changing their order.Striation
Updated. Leaving the order the same, since that matches the Python docs.Alicea
you don't need pytz just to get utc tzinfo object. It is easy to create it yourselfLeannleanna
M
10

Note that datetime.datetime.fromtimestamp(timestamp) and .utcfromtimestamp(timestamp) fail on windows for dates before Jan. 1, 1970 while negative unix timestamps seem to work on unix-based platforms. The docs say this:

"This may raise ValueError, if the timestamp is out of the range of values supported by the platform C gmtime() function. It’s common for this to be restricted to years in 1970 through 2038"

See also Issue1646728

Mockheroic answered 15/5, 2013 at 16:44 Comment(3)
:o) yes, still some 23 years to let it get fixedApo
you could use utc_time = datetime(1970,1,1) + timedelta(seconds=timestamp), to workaround it.Leannleanna
This is a problem. There are many people who are born before 1970 or Dec 31 1969 in the US! Those DOBs stored in Java may break intraoperatively then.Styliform
P
7

For those that want it ISO 8601 compliant, since the other solutions do not have the T separator nor the time offset (except Meistro's answer):

from datetime import datetime, timezone
result = datetime.fromtimestamp(1463288494, timezone.utc).isoformat('T', 'microseconds')
print(result) # 2016-05-15T05:01:34.000000+00:00

Note, I use fromtimestamp because if I used utcfromtimestamp I would need to chain on .astimezone(...) anyway to get the offset.

If you don't want to go all the way to microseconds you can choose a different unit with the isoformat() method.

Peggie answered 2/12, 2020 at 13:49 Comment(0)
R
0

Seconds (or minutes or hours etc.) are time differences, i.e. timedelta, so another approach is to cast the seconds into a timedelta object and add it to the UNIX epoch (which is 1970-01-01 00:00:00 UTC).

from datetime import datetime, timedelta, UTC
# for UTC datetime
datetime.fromtimestamp(0, UTC) + timedelta(seconds=1284286794)
# ^^^^^ UNIX epoch

# for naive datetime
datetime.fromtimestamp(0) + timedelta(seconds=1284286794)

This approach works for timestamps before the epoch (i.e. negative seconds) as well, unlike directly passing a negative number to fromtimestamp, which raises an OSError (at least on Windows).

datetime.fromtimestamp(0, UTC) + timedelta(seconds=-1284286794)

On a somewhat related note, if you're already using numpy, then you can use np.datetime64 to cast integers into datetimes as well. The integers are interpreted as offsets relative to the UNIX epoch. You just need to pass the unit using [s] (for seconds). Nice thing about numpy is that you can cast an entire list of seconds into an array of datetimes vectorially.

np.array([1284286794, 0, -1284286794], dtype='datetime64[s]')
Rosena answered 4/4 at 18:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.