Convert an RFC 3339 time to a standard Python timestamp

喜你入骨 提交于 2019-11-27 20:38:58

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. :-)

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

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.

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.

Amber

http://bugs.python.org/issue15873 (duplicate of http://bugs.python.org/issue5207 )

Looks like there isn't a built-in as of yet.

feedparser.py provides robust/extensible way to parse various date formats that may be encountered in real-world atom/rss feeds:

>>> from feedparser import _parse_date as parse_date
>>> parse_date('1985-04-12T23:20:50.52Z')
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)

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>)
dfostic

try this, it works fine for me

datetime_obj =  datetime.strptime("2014-01-01T00:00:00Z", '%Y-%m-%dT%H:%M:%SZ')

or

datetime_obj = datetime.strptime("Mon, 01 Jun 2015 16:41:40 GMT", '%a, %d %b %Y %H:%M:%S GMT')

Using Python 3, you can use RegEx to break the RFC 3339 timestamp into its components. Then, directly create the datetime object, no additional modules needed:

import re
import datetime

def parse_rfc3339(dt):
    broken = re.search(r'([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(\.([0-9]+))?(Z|([+-][0-9]{2}):([0-9]{2}))', dt)
    return(datetime.datetime(
        year = int(broken.group(1)),
        month = int(broken.group(2)),
        day = int(broken.group(3)),
        hour = int(broken.group(4)),
        minute = int(broken.group(5)),
        second = int(broken.group(6)),
        microsecond = int(broken.group(8) or "0"),
        tzinfo = datetime.timezone(datetime.timedelta(
            hours = int(broken.group(10) or "0"),
            minutes = int(broken.group(11) or "0")))))

This example theads missing timezones or microseconds as "0" but might need additional error checking. Cheers, Alex

Bolster

Came across the awesome dateutil.parser module in another question, and tried it on my RFC3339 problem, and it appears to handle everything I throw at it with more sanity that any of the other responses in this question.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!