1108

I have a string representing a unix timestamp (i.e. "1284101485") in Python, and I'd like to convert it to a readable date. When I use time.strftime, I get a TypeError:

>>>import time
>>>print time.strftime("%B %d %Y", "1284101485")

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: argument must be 9-item sequence, not str
kabr8
  • 341
  • 1
  • 2
  • 19
VeryNewToPython
  • 11,113
  • 3
  • 15
  • 3

19 Answers19

1551

Use datetime module:

from datetime import datetime
ts = int('1284101485')

# if you encounter a "year is out of range" error the timestamp
# may be in milliseconds, try `ts /= 1000` in that case
print(datetime.utcfromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S'))
Jaroslav Bezděk
  • 6,967
  • 6
  • 29
  • 46
Michał Niklas
  • 53,067
  • 18
  • 70
  • 114
  • 161
    `.fromtimestamp()` might fail for past dates if a local timezone had different utc offset. You need a historic timezone database such as provided by `pytz` module (or your OS). Or just work in UTC and use `.utcfromtimestamp()`. – jfs Nov 23 '13 at 01:08
  • 11
    @J.F.Sebastian You've mentioned this might fail in a couple of comments - please could you elaborate as to why it would fail for a past dates/times? (Judging by the upvotes, many people both agree with you and see this as straightforward) Surely any unix timestamp has a simple equivalent date/time? – davidhood2 Nov 22 '16 at 09:16
  • 4
    @davidhood2 take a system where python has no access to [the tz database](https://en.wikipedia.org/wiki/Tz_database) (Windows), set your local timezone to a timezone that had a different UTC offset in the past (e.g. Europe/Moscow), call fromtimestamp() with timestamps from the past (2011-). Compare the results with values computed using `pytz`. If it is unclear; ask a separate Stack Overflow question. – jfs Nov 22 '16 at 14:10
  • 4
    @davidhood2: I've posted [my own answer that demonstrates the `pytz` solution](http://stackoverflow.com/a/40769643/4279). – jfs Nov 23 '16 at 16:31
  • 10
    An import point is this takes a timestamp in seconds since the epoch; if you have milliseconds you have to divide by 1000 as I just found out. – wordsforthewise Jun 13 '17 at 18:28
  • 1
    Is there an advantage of using `strftime` over `"{:%Y-%m-%d %H:%M:%S}".format(dateobj)`? – Martin Thoma Aug 10 '17 at 13:02
  • According to Python documentation `__format__()` is same as `strftime()` but I simply prefer `strftime()`. – Michał Niklas Aug 11 '17 at 09:19
  • 1
    If you are getting `ValueError: year VALUE is out of range`, that means you are working with milliseconds(Unix timestamp is 13 digits). The above function works only if Unix timestamp in seconds. If you are working with milliseconds, divide that value by 1000. https://stackoverflow.com/q/31548132/2960555 – unknownerror Oct 30 '17 at 09:44
  • What if I want to include milliseconds? – User Oct 20 '18 at 23:48
  • @User pass a float e.g., if you have `1234` milliseconds then pass `1.234` seconds (it is easy to divide by 1000 on the decimal system: just move the decimal dot 3 positions to the left). – jfs Dec 27 '18 at 15:41
  • or just `datetime.datetime.utcfromtimestamp(1398385815)` – prayagupa Apr 18 '19 at 19:40
321
>>> from datetime import datetime
>>> datetime.fromtimestamp(1172969203.1)
datetime.datetime(2007, 3, 4, 0, 46, 43, 100000)

Taken from http://seehuhn.de/pages/pdate

Daniel
  • 3,741
  • 1
  • 16
  • 21
  • This method return an datetime.datetime object. This can be printed as it has the magic __str__() method included. Also check out the [best comment][1], so `print(datetime.utcfromtimestamp(unix_time_value)` will make it human-readable. [1]: https://stackoverflow.com/questions/3682748/converting-unix-timestamp-string-to-readable-date#comment30046351_3682808 – PythoNic Jul 13 '22 at 19:30
196

The most voted answer suggests using fromtimestamp which is error prone since it uses the local timezone. To avoid issues a better approach is to use UTC:

datetime.datetime.utcfromtimestamp(posix_time).strftime('%Y-%m-%dT%H:%M:%SZ')

Where posix_time is the Posix epoch time you want to convert

rkachach
  • 16,517
  • 6
  • 42
  • 66
  • 2
    import datetime, pytz datetime.datetime(1990, 1, 1, tzinfo=pytz.utc) – y.selivonchyk Jun 23 '17 at 18:09
  • beware, unix time might be different from posix time in (rare) cases e.g., `TZ=right/UTC date` vs. `TZ=UTC date` is `Mon 7 Sep 15:58:05 UTC 2020` vs. `Mon 7 Sep 15:58:32 UTC 2020` (the difference may change depending on the number of leap seconds) – jfs Sep 07 '20 at 15:58
  • 2
    `ValueError: year 53085 is out of range` – alper Feb 11 '21 at 17:36
  • 7
    @alper In such cases, likely one has a timestamp in milliseconds; try dividing by 1000. Or by 1000000 if the timestamp is in microseconds. – ShreevatsaR Jun 20 '21 at 21:22
  • What exactly does "it uses the local timezone" mean? Does it assume that the timestamp refers to the number of seconds elapsed since 1/1/70 in the local timezone? Or does it correctly assume the timestamp is the number of seconds since 1/1/70 in UTC, and then express the resulting date/time in the local timezone? – Jack M Jan 18 '23 at 17:21
92

There are two parts:

  1. Convert the unix timestamp ("seconds since epoch") to the local time
  2. Display the local time in the desired format.

A portable way to get the local time that works even if the local time zone had a different utc offset in the past and python has no access to the tz database is to use a pytz timezone:

#!/usr/bin/env python
from datetime import datetime
import tzlocal  # $ pip install tzlocal

unix_timestamp = float("1284101485")
local_timezone = tzlocal.get_localzone() # get pytz timezone
local_time = datetime.fromtimestamp(unix_timestamp, local_timezone)

To display it, you could use any time format that is supported by your system e.g.:

print(local_time.strftime("%Y-%m-%d %H:%M:%S.%f%z (%Z)"))
print(local_time.strftime("%B %d %Y"))  # print date in your format

If you do not need a local time, to get a readable UTC time instead:

utc_time = datetime.utcfromtimestamp(unix_timestamp)
print(utc_time.strftime("%Y-%m-%d %H:%M:%S.%f+00:00 (UTC)"))

If you don't care about the timezone issues that might affect what date is returned or if python has access to the tz database on your system:

local_time = datetime.fromtimestamp(unix_timestamp)
print(local_time.strftime("%Y-%m-%d %H:%M:%S.%f"))

On Python 3, you could get a timezone-aware datetime using only stdlib (the UTC offset may be wrong if python has no access to the tz database on your system e.g., on Windows):

#!/usr/bin/env python3
from datetime import datetime, timezone

utc_time = datetime.fromtimestamp(unix_timestamp, timezone.utc)
local_time = utc_time.astimezone()
print(local_time.strftime("%Y-%m-%d %H:%M:%S.%f%z (%Z)"))

Functions from the time module are thin wrappers around the corresponding C API and therefore they may be less portable than the corresponding datetime methods otherwise you could use them too:

#!/usr/bin/env python
import time

unix_timestamp  = int("1284101485")
utc_time = time.gmtime(unix_timestamp)
local_time = time.localtime(unix_timestamp)
print(time.strftime("%Y-%m-%d %H:%M:%S", local_time)) 
print(time.strftime("%Y-%m-%d %H:%M:%S+00:00 (UTC)", utc_time))  
jfs
  • 399,953
  • 195
  • 994
  • 1,670
  • It should be the most voted answer if you care about local time. – azzamsa Sep 20 '19 at 02:50
  • if you get ValueError: year xxx is out of range error divide your timestamp to /1000 https://stackoverflow.com/a/31548402/1428241 – Barlas Apaydin May 06 '21 at 23:20
  • @jfs is there a similar method to convert back from date-time string back to the Unix timestamp? – ENV Jun 10 '21 at 11:59
  • @ENV: once you've parsed your input time string into an aware datetime object, just call its `.timestamp()` method. How to convert the time string depends on its format -- it is ambiguous in the general case but there are many solution for various cases. – jfs Jun 10 '21 at 18:36
91
>>> import time
>>> time.ctime(int("1284101485"))
'Fri Sep 10 16:51:25 2010'
>>> time.strftime("%D %H:%M", time.localtime(int("1284101485")))
'09/10/10 16:51'
John La Rooy
  • 295,403
  • 53
  • 369
  • 502
  • 12
    `time.ctime()` and `time.localtime()` might fail for past dates if a local timezone had different utc offset. You need a historic timezone database such as provided by `pytz` module (or your OS). Or just work in UTC and use `time.gmtime()`. `datetime` might provide wider date range so `datetime.utcfromtimestamp()` could be used instead of `time` functions. – jfs Nov 23 '13 at 01:30
  • @John La Rooy is there a similar method to convert back from date-time string back to the Unix timestamp? – ENV Jun 10 '21 at 11:58
79

In Python 3.6+:

import datetime

timestamp = 1642445213
value = datetime.datetime.fromtimestamp(timestamp)
print(f"{value:%Y-%m-%d %H:%M:%S}")

Output (local time)

2022-01-17 20:46:53

Explanation

Bonus

To save the date to a string then print it, use this:

my_date = f"{value:%Y-%m-%d %H:%M:%S}"
print(my_date)

To output in UTC:

value = datetime.datetime.fromtimestamp(timestamp, tz=datetime.timezone.utc)
# 2022-01-17 18:50:52
Contango
  • 76,540
  • 58
  • 260
  • 305
45

Other than using time/datetime package, pandas can also be used to solve the same problem.Here is how we can use pandas to convert timestamp to readable date:

Timestamps can be in two formats:

  1. 13 digits(milliseconds) - To convert milliseconds to date, use:

    import pandas
    result_ms=pandas.to_datetime('1493530261000',unit='ms')
    str(result_ms)
    
    Output: '2017-04-30 05:31:01'
    
  2. 10 digits(seconds) - To convert seconds to date, use:

    import pandas
    result_s=pandas.to_datetime('1493530261',unit='s')
    str(result_s)
    
    Output: '2017-04-30 05:31:01'
    
shubham
  • 576
  • 4
  • 7
37

For a human readable timestamp from a UNIX timestamp, I have used this in scripts before:

import os, datetime

datetime.datetime.fromtimestamp(float(os.path.getmtime("FILE"))).strftime("%B %d, %Y")

Output:

'December 26, 2012'

Jared Burrows
  • 54,294
  • 25
  • 151
  • 185
29

You can convert the current time like this

t=datetime.fromtimestamp(time.time())
t.strftime('%Y-%m-%d')
'2012-03-07'

To convert a date in string to different formats.

import datetime,time

def createDateObject(str_date,strFormat="%Y-%m-%d"):    
    timeStamp = time.mktime(time.strptime(str_date,strFormat))
    return datetime.datetime.fromtimestamp(timeStamp)

def FormatDate(objectDate,strFormat="%Y-%m-%d"):
    return objectDate.strftime(strFormat)

Usage
=====
o=createDateObject('2013-03-03')
print FormatDate(o,'%d-%m-%Y')

Output 03-03-2013
Nick
  • 1,799
  • 3
  • 23
  • 32
24
timestamp ="124542124"
value = datetime.datetime.fromtimestamp(timestamp)
exct_time = value.strftime('%d %B %Y %H:%M:%S')

Get the readable date from timestamp with time also, also you can change the format of the date.

Alberto Bonsanto
  • 17,556
  • 10
  • 64
  • 93
Rishabh Jhalani
  • 1,049
  • 13
  • 22
  • 7
    What does this answer add to [this](https://stackoverflow.com/a/21578729/8254699) answer? – kocica Dec 30 '18 at 10:42
  • 1
    Please add a warning related to issue of local timezone assumption. Best practices in programming is to store timestamps as UTC times instead of local timestamps. But this example above will return the wrong time if the local timezone is not UTC. – Timothy C. Quinn May 12 '19 at 16:01
12

Note that utcfromtimestamp can lead to unexpected results since it returns a naive datetime object. Python treats naive datetime as local time - while UNIX time refers to UTC.

This ambiguity can be avoided by setting the tz argument in fromtimestamp:

from datetime import datetime, timezone

dtobj = datetime.fromtimestamp(1284101485, timezone.utc)

>>> print(repr(dtobj))
datetime.datetime(2010, 9, 10, 6, 51, 25, tzinfo=datetime.timezone.utc)

Now you can format to string, e.g. an ISO8601 compliant format:

>>> print(dtobj.isoformat(timespec='milliseconds').replace('+00:00', 'Z'))
2010-09-10T06:51:25.000Z
FObersteiner
  • 22,500
  • 8
  • 42
  • 72
9

Use the following codes, I hope it will solve your problem.

import datetime as dt

print(dt.datetime.fromtimestamp(int("1284101485")).strftime('%Y-%m-%d %H:%M:%S'))
Rachel Gallen
  • 27,943
  • 21
  • 72
  • 81
Deepak
  • 101
  • 1
  • 1
8

Use datetime.strftime(format):

from datetime import datetime
unixtime = int('1284101485')

# Print with local time
print(datetime.fromtimestamp(unixtime).strftime('%Y-%m-%d %H:%M:%S'))

# Print with UTC time
print(datetime.utcfromtimestamp(unixtime).strftime('%Y-%m-%d %H:%M:%S'))
Nick Tsai
  • 3,799
  • 33
  • 36
7
import datetime
temp = datetime.datetime.fromtimestamp(1386181800).strftime('%Y-%m-%d %H:%M:%S')
print temp
itsaruns
  • 659
  • 2
  • 11
  • 16
6

Another way that this can be done using gmtime and format function;

from time import gmtime
print('{}-{}-{} {}:{}:{}'.format(*gmtime(1538654264.703337)))

Output: 2018-10-4 11:57:44

h3xus
  • 63
  • 1
  • 5
4

If you are working with a dataframe and do not want the series cannot be converted to class int error. Use the code below.

new_df= pd.to_datetime(df_new['time'], unit='s')
MD Mushfirat Mohaimin
  • 1,966
  • 3
  • 10
  • 22
tym
  • 63
  • 8
1

i just successfully used:

>>> type(tstamp)
pandas.tslib.Timestamp
>>> newDt = tstamp.date()
>>> type(newDt)
datetime.date
nimmy
  • 29
  • 1
1

You can use easy_date to make it easy:

import date_converter
my_date_string = date_converter.timestamp_to_string(1284101485, "%B %d, %Y")
Raphael Amoedo
  • 4,233
  • 4
  • 28
  • 37
  • 5
    Every programming has it's own date and time converters. One should never have to use mods/frameworks for this – Jos Dec 09 '15 at 14:55
  • 1
    `strptime` and `strftime` isn't intuitive... And even not readable... But I understand and respect your opinion – Raphael Amoedo Dec 09 '15 at 18:06
  • 6
    That one should "never have to use" is wrong. It depends on the language and the quality of the built-in libs. Javascript has moments.js and Java had Joda time which both are more popular than the respective built-in date and time conversion utils (so much that Joda time later influenced Java 8's updated standard libs). That said, unless the question calls for nice third-party libraries, it's preferable to give an answer based on the standard library. – Hejazzman Dec 22 '15 at 23:57
  • 1
    I stand corrected @NikosVentouras. I've just had the "JS Date in IE behaves differently" issue for the first time. So I ended up using moment.js – Jos Jan 19 '16 at 10:28
0

quick and dirty one liner:

'-'.join(str(x) for x in list(tuple(datetime.datetime.now().timetuple())[:6]))

'2013-5-5-1-9-43'

eqzx
  • 5,323
  • 4
  • 37
  • 54
  • 3
    Or more concisely: '-'.join(map(str, datetime.datetime.now().timetuple()[:6])) – Jelle Zijlstra Jun 11 '14 at 04:23
  • 2
    @JelleZijlstra Eh, I much prefer the generator expression over map. – crhodes Aug 24 '15 at 11:08
  • 6
    What kind of date format is '2013-5-5-1-9-43' ? I've never seen this format anywhere as a valid representation of a date/time. – madoki Feb 09 '16 at 18:18
  • can you elaborate on what qualifies this as an invalid representation @madoki ? do you mean nonstandard? The primary advantage it has over most other answers is the ability to include it in a file or directory path, as spaces and colons are not in the set of standard unix directory characters. see e.g. https://stackoverflow.com/a/458001/209246 – eqzx Feb 22 '18 at 22:07