Convert an RFC 3339 time to a standard Python timestamp
Solution 1
No builtin, afaik.
feed.date.rfc3339 This is a Python library module with functions for converting timestamp strings in RFC 3339 format to Python time float values, and vice versa. RFC 3339 is the timestamp format used by the Atom feed syndication format.
It is BSD-licensed.
http://home.blarg.net/~steveha/pyfeed.html
(Edited so it's clear I didn't write it. :-)
Solution 2
You don't include an example, but if you don't have a Z-offset or timezone, and assuming you don't want durations but just the basic time, then maybe this will suit you:
import datetime as dt
>>> dt.datetime.strptime('1985-04-12T23:20:50.52', '%Y-%m-%dT%H:%M:%S.%f')
datetime.datetime(1985, 4, 12, 23, 20, 50, 520000)
The strptime() function was added to the datetime module in Python 2.5 so some people don't yet know it's there.
Edit: The time.strptime() function has existed for a while though, and works about the same to give you a struct_time value:
>>> ts = time.strptime('1985-04-12T23:20:50.52', '%Y-%m-%dT%H:%M:%S.%f')
>>> ts
time.struct_time(tm_year=1985, tm_mon=4, tm_mday=12, tm_hour=23, tm_min=20, tm_sec=50, tm_wday=4, tm_yday=102, tm_isdst=-1)
>>> time.mktime(ts)
482210450.0
Solution 3
I struggled with RFC3339 datetime format a lot, but I found a suitable solution to convert date_string <=> datetime_object in both directions.
You need two different external modules, because one of them is is only able to do the conversion in one direction (unfortunately):
first install:
sudo pip install rfc3339
sudo pip install iso8601
then include:
import datetime # for general datetime object handling
import rfc3339 # for date object -> date string
import iso8601 # for date string -> date object
For not needing to remember which module is for which direction, I wrote two simple helper functions:
def get_date_object(date_string):
return iso8601.parse_date(date_string)
def get_date_string(date_object):
return rfc3339.rfc3339(date_object)
which inside your code you can easily use like this:
input_string = '1989-01-01T00:18:07-05:00'
test_date = get_date_object(input_string)
# >>> datetime.datetime(1989, 1, 1, 0, 18, 7, tzinfo=<FixedOffset '-05:00' datetime.timedelta(-1, 68400)>)
test_string = get_date_string(test_date)
# >>> '1989-01-01T00:18:07-05:00'
test_string is input_string # >>> True
Heureka! Now you can easily (haha) use your date strings and date strings in a useable format.
Solution 4
If you're using Django, you could use Django's function parse_datetime
:
>>> from django.utils.dateparse import parse_datetime
>>> parse_datetime("2016-07-19T07:30:36+05:00")
datetime.datetime(2016, 7, 19, 7, 30, 36, tzinfo=<django.utils.timezone.FixedOffset object at 0x101c0c1d0>)
Solution 5
http://pypi.python.org/pypi/iso8601/ seems to be able to parse iso 8601, which RFC 3339 is a subset of, maybe this could be useful, but again, not built-in.
Mark Biek
Updated on January 20, 2021Comments
-
Mark Biek over 3 years
Is there an easy way to convert an RFC 3339 time into a regular Python timestamp?
I've got a script which is reading an ATOM feed and I'd like to be able to compare the timestamp of an item in the ATOM feed to the modification time of a file.
I notice from the ATOM spec, that ATOM dates include a time zone offset (
Z<a number>
) but, in my case, there's nothing after theZ
so I guess we can assume GMT.I suppose I could parse the time with a regex of some sort but I was hoping Python had a built-in way of doing it that I just haven't been able to find.
-
steveha over 13 yearsIf you read the RFC 3339 spec, you will see that the only valid time zone offset values are: (0) a bare "Z", meaning the time stamp is UTC; or (1) an offset of the form "[+-]\d\d:\d\d" such as "+02:00" or "-08:00". Note that an offset of "+00:00" would mean the same thing as "Z". For more details, read the RFC 3339 spec: tools.ietf.org/html/rfc3339
-
jfs over 10 years
-
jfs over 8 years
-
-
steveha over 14 yearsAlso, I wrote the PyFeed (and Xe) libraries, and I hang out here on StackOverflow, so if you have any questions about it, I would be happy to answer them.
-
Mark Biek over 14 yearsPyFeed does exactly what I need, courtesy of the tf_from_timestamp() function in feed.date.rfc3339
-
steveha over 14 yearsNote that PyFeed can be used to parse an Atom feed. It uses xml.dom.minidom to do the actual parsing, and then unpacks the XML tree structure into nice convenient classes. Hmm, I ought to put Xe and PyFeed up on PyPI.
-
Mark Biek over 14 years@steveha Excellent, thanks for the offer. The libraries seem pretty easy to use so far but I'll remember you're here if I run into anything weird.
-
steveha over 14 years@Alex Brasetvik, it was already clear that you were not claiming to have written it. If you were claiming credit you wouldn't have included the direct link to my web page! P.S. I was happy to see you recommending my library; thank you.
-
Ram Rachum over 13 yearsThis seems much nicer than the "time floats" offered by PyFeed.
-
steveha over 13 yearscool-NR, if you have a time float value, you can call
time.gmtime()
and get thestruct_time
value. And it is a lot easier to do relative times with a time float value; two days from now is simplytf + 2 * seconds_per_day
(whereseconds_per_day
is 24 * 60 * 60). Python'sstruct_time
is great for inspecting (what day of the week is it?) but terribly inconvenient for computing. -
Tobu almost 13 yearsTime floats and struct_time aren't timezone aware. Since RFC 3339 requires UTC-compatible time zones, which in Python means non-naive
datetime
objects, this is the only sane option so far. -
Yarin over 12 yearslink's broken- should it be code.google.com/p/feedparser/source/browse/trunk/feedparser/…?
-
Yarin over 12 yearsThis won't work- Methods that are not time-zone aware are not RFC 3339 compatible.
-
Peter Hansen over 12 yearsYarin, clearly, but your complaint should be with the original question's use of "RFC 3339" then, as my answer did address his actual question, where he notes he doesn't have a time zone...
-
Yarin over 12 yearsPeter- The way I read his question he's trying to compare an ATOM feed RFC 3999 date with timezone to another date with assumed GMT, but maybe i don't get it
-
Romuald Brunet over 11 yearsThe only problem being that it also parses non-date values like "now"
-
jfs almost 9 years@Yarin: "there's nothing after the Z" -- it means the input is UTC and
strptime()
could be used. Thoughmktime()
that expects time in the local timezone should not be used.calendar.timegm()
could be used instead (to compare with the result ofos.path.getmtime()
: "I'd like to be able to compare the timestamp of an item in the ATOM feed to the modification time of a file.") -
jfs almost 9 years
-
Lennart Rolland over 4 yearsIt does not keep milliseconds?
-
jfs over 4 years@LennartRolland: yes.
time.struct_time
doesn't store fractions of a second. -
Ross Smith II about 2 yearsPython 3.10.4 reported
Invalid isoformat string: '2022-05-08T02:47:35.839Z'