I have dt = datetime(2013,9,1,11)
, and I would like to get a Unix timestamp of this datetime object.
When I do (dt - datetime(1970,1,1)).total_seconds()
I got the timestamp 1378033200
.
When converting it back using datetime.fromtimestamp
I got datetime.datetime(2013, 9, 1, 6, 0)
.
The hour doesn't match. What did I miss here?
For working with UTC timezones:
time_stamp = calendar.timegm(dt.timetuple())
datetime.utcfromtimestamp(time_stamp)
solution is
import time
import datetime
d = datetime.date(2015,1,5)
unixtime = time.mktime(d.timetuple())
Well, when converting TO unix timestamp, python is basically assuming UTC, but while converting back it will give you a date converted to your local timezone.
See this question/answer; Get timezone used by datetime.datetime.fromtimestamp()
If your datetime object represents UTC time, don't use time.mktime, as it assumes the tuple is in your local timezone. Instead, use calendar.timegm:
>>> import datetime, calendar
>>> d = datetime.datetime(1970, 1, 1, 0, 1, 0)
>>> calendar.timegm(d.timetuple())
60
def dt2ts(dt, utc=False):
if utc:
return calendar.timegm(dt.timetuple())
if dt.tzinfo is None:
return int(time.mktime(dt.timetuple()))
utc_dt = dt.astimezone(tz.tzutc()).timetuple()
return calendar.timegm(utc_dt)
If you want UTC timestamp :time.mktime
just for local dt .Use calendar.timegm
is safe but dt must the utc zone so change the zone to utc. If dt in UTC just use calendar.timegm
.
Rather than this expression to create a POSIX timestamp from dt
,
(dt - datetime(1970,1,1)).total_seconds()
Use this:
int(dt.strftime("%s"))
I get the right answer in your example using the second method.
EDIT: Some followup... After some comments (see below), I was curious about the lack of support or documentation for %s
in strftime
. Here's what I found:
In the Python source for datetime
and time
, the string STRFTIME_FORMAT_CODES
tells us:
"Other codes may be available on your platform.
See documentation for the C library strftime function."
So now if we man strftime
(on BSD systems such as Mac OS X), you'll find support for %s
:
"%s is replaced by the number of seconds since the Epoch, UTC (see mktime(3))."
Anyways, that's why %s
works on the systems it does. But there are better solutions to OP's problem (that take timezones into account). See @abarnert's accepted answer here.
This class will cover your needs, you can pass the variable into ConvertUnixToDatetime & call which function you want it to operate based off.
from datetime import datetime
import time
class ConvertUnixToDatetime:
def __init__(self, date):
self.date = date
# Convert unix to date object
def convert_unix(self):
unix = self.date
# Check if unix is a string or int & proceeds with correct conversion
if type(unix).__name__ == 'str':
unix = int(unix[0:10])
else:
unix = int(str(unix)[0:10])
date = datetime.utcfromtimestamp(unix).strftime('%Y-%m-%d %H:%M:%S')
return date
# Convert date to unix object
def convert_date(self):
date = self.date
# Check if datetime object or raise ValueError
if type(date).__name__ == 'datetime':
unixtime = int(time.mktime(date.timetuple()))
else:
raise ValueError('You are trying to pass a None Datetime object')
return type(unixtime).__name__, unixtime
if __name__ == '__main__':
# Test Date
date_test = ConvertUnixToDatetime(datetime.today())
date_test = date_test.convert_date()
print(date_test)
# Test Unix
unix_test = ConvertUnixToDatetime(date_test[1])
print(unix_test.convert_unix())
You've missed the time zone info (already answered, agreed)
arrow
package allows to avoid this torture with datetimes; It is already written, tested, pypi-published, cross-python (2.6 — 3.xx).
All you need: pip install arrow
(or add to dependencies)
dt = datetime(2013,9,1,11)
arrow.get(dt).timestamp
# >>> 1378033200
bc = arrow.get(1378033200).datetime
print(bc)
# >>> datetime.datetime(2013, 9, 1, 11, 0, tzinfo=tzutc())
print(bc.isoformat())
# >>> '2013-09-01T11:00:00+00:00'
def datetime_to_epoch(d1):
# create 1,1,1970 in same timezone as d1
d2 = datetime(1970, 1, 1, tzinfo=d1.tzinfo)
time_delta = d1 - d2
ts = int(time_delta.total_seconds())
return ts
def epoch_to_datetime_string(ts, tz_name="UTC"):
x_timezone = timezone(tz_name)
d1 = datetime.fromtimestamp(ts, x_timezone)
x = d1.strftime("%d %B %Y %H:%M:%S")
return x
If you want to convert a python datetime to seconds since epoch you should do it explicitly:
>>> import datetime
>>> datetime.datetime(2012, 04, 01, 0, 0).strftime('%s')
'1333234800'
>>> (datetime.datetime(2012, 04, 01, 0, 0) - datetime.datetime(1970, 1, 1)).total_seconds()
1333238400.0
In Python 3.3+ you can use timestamp()
instead:
>>> import datetime
>>> datetime.datetime(2012, 4, 1, 0, 0).timestamp()
1333234800.0
Source: Stackoverflow.com