3

Users in my app have date_joined fields that are in this format: 2014-12-14 14:46:43.379518+00:00

In order to pass this datetime along to Intercom.io, it must be a UNIX timestamp like this: 1426020706 (this is not the same time, just an example).

I've tried several methods I've read here on Stack Overflow (nothing in this question has the same starting time format: Converting datetime.date to UTC timestamp in Python), but none have worked. mktime() seemed promising, but I got "'datetime.datetime' object has no attribute 'mktime'."

I just tried this:

import time
import dateutil.parser
import member.models import Member

member = Member.objects.get(email="aspeksnijder@outlook.com")
date_joined = member.date_joined
dt = dateutil.parser.parse(date_joined)
print int(time.mktime(dt.timetuple()))

It returned "'datetime.datetime' object has no attribute 'read'". How can I accomplish this?

Community
  • 1
  • 1
Michelle Glauser
  • 1,097
  • 16
  • 28
  • possible duplicate of [Converting datetime.date to UTC timestamp in Python](http://stackoverflow.com/questions/8777753/converting-datetime-date-to-utc-timestamp-in-python) – heinst Mar 14 '15 at 20:32
  • http://stackoverflow.com/questions/1287598/datetime-time-has-no-mktime – heinst Mar 14 '15 at 20:36
  • 1
    It looks like member.date_joined is already a datetime object, and there's no need to parse it. – Peter Feb 25 '17 at 00:33

5 Answers5

4

It seems you have an aware datetime object. If you print it then it looks like:

2014-12-14 14:46:43.379518+00:00

To be sure print(repr(date_joined)).

Converting datetime.date to UTC timestamp in Python shows several ways how you could get the timestamp e.g.,

timestamp = date_joined.timestamp() # in Python 3.3+

Or on older Python versions:

from datetime import datetime

# local time = utc time + utc offset
utc_naive = date_joined.replace(tzinfo=None) - date_joined.utcoffset()
timestamp = (utc_naive - datetime(1970, 1, 1)).total_seconds()

Note: timestamp = calendar.timegm(date_joined.utctimetuple()) would also work in your case but it may return a wrong result silently if you pass it a naive datetime object that represents local time by mistake.

If your input is a time string then convert the time string into a datetime object first.

Community
  • 1
  • 1
jfs
  • 399,953
  • 195
  • 994
  • 1,670
3

What about (using the dateutil and pytz packages):

import dateutil.parser
from datetime import datetime
import calendar
import pytz

def str2ts(s):
    ''' Turns a string into a non-naive datetime object, then get the timestamp '''
    # However you get from your string to datetime.datetime object
    dt = dateutil.parser.parse(s)           # String to non-naive datetime
    dt = pytz.utc.normalize(dt)             # Normalize datetime to UTC
    ts = calendar.timegm(dt.timetuple())    # Convert UTC datetime to UTC timestamp
    return int(ts)

def ts2str(ts):
    '''Convert a UTC timestamp into a UTC datetime, then format it to a string'''
    dt = datetime.utcfromtimestamp(ts)      # Convert a UTC timestamp to a naive datetime object
    dt = dt.replace(tzinfo=pytz.utc)        # Convert naive datetime to non-naive
    return dt.strftime('%Y-%m-%d %H:%M:%S.%f%z')

Which we can test with:

# A list of strings corresponding to the same time, with different timezone offsets
ss = [
    '2014-12-14 14:46:43.379518+00:00',
    '2014-12-14 15:46:43.379518+01:00',
    '2014-12-14 16:46:43.379518+02:00',
    '2014-12-14 17:46:43.379518+03:00',
]    

for s in ss:
    ts = str2ts(s)
    s2 = ts2str(ts)

    print ts, s2

Output:

1418568403 2014-12-14 14:46:43.000000+0000
1418568403 2014-12-14 14:46:43.000000+0000
1418568403 2014-12-14 14:46:43.000000+0000
1418568403 2014-12-14 14:46:43.000000+0000

These output all the same timestamps, and "verification" formatted strings.

jedwards
  • 29,432
  • 3
  • 65
  • 92
  • I tried that and got this: "AttributeError: 'datetime.datetime' object has no attribute 'read'" – Michelle Glauser Mar 14 '15 at 20:53
  • 1
    It looks like doing "date_joined = str(member.date_joined)" worked. – Michelle Glauser Mar 14 '15 at 20:55
  • @jedwards the parse function cannot handle timezones – heinst Mar 14 '15 at 21:01
  • @heinst `dateutil.parser.parse` handles timezones fine (see: `print(repr(dateutil.parser.parse()))`) -- however, I assumed that all the strings would be in UTC -- I'll update my answer with a more robust solution. – jedwards Mar 14 '15 at 21:19
  • Updated with code that will correctly handle strings with different timezone offsets. – jedwards Mar 14 '15 at 21:37
  • @MichelleGlauser: do not convert `date_joined` to string if you want to get the timestamp. The error message says that you already have `datetime` object. You do not need `dateutil.parser.parse` here. – jfs Mar 15 '15 at 11:42
2

You can try the following Python 3 code:

import time, datetime
print(time.mktime(datetime.datetime.strptime("2014-12-14 14:46:43.379518", '%Y-%m-%d %H:%M:%S.%f').replace(tzinfo=datetime.timezone.utc).timetuple()))

which prints:

1418568403.0
kenorb
  • 155,785
  • 88
  • 678
  • 743
  • downvote: `mktime()` is wrong unless the local timezone is utc (notice: `+00:00` in the question) – jfs Jan 20 '16 at 21:19
1

I had that problem when I used input from Django's DateField, which is displayed in a form of XXXX-YY-ZZ: parse(django_datefield) causes the exception.

The solution: use str(django_datefield).

parse(str(django_datefield))
Nathaniel Ford
  • 20,545
  • 20
  • 91
  • 102
  • 1
    downvote. Why would you convert a `datetime` object into a string only to parse it back? – jfs Jan 20 '16 at 21:21
0

I know this is an old post, but I want to highlight that the answer is likely what @Peter said in his comment:

It looks like member.date_joined is already a datetime object, and there's no need to parse it. – Peter Feb 25 '17 at 0:33

So-- your model probably already parses into a datetime.datetime object for you.

thekingoftruth
  • 1,711
  • 1
  • 25
  • 24