2009-12-21 477 views
13

有沒有簡單的方法將RFC 3339時間轉換爲常規Python時間戳?將RFC 3339時間轉換爲標準Python時間戳

我有一個腳本正在讀取一個ATOM feed,我希望能夠比較一個項目在ATOM feed中的時間戳與文件的修改時間。

我從ATOM spec注意到,該原子日期包括時區偏移量(Z<a number>),但於我而言,沒有什麼後Z所以我想我們可以假設GMT。

我想我可以用某種類型的正則表達式解析時間,但是我希望Python有一個內置的方法來做到這一點,我一直沒有找到。

+2

如果你讀了RFC 3339規範,你會看到,唯一有效的時區偏移值是:( 0)裸露的「Z」,表示時間戳是UTC;或(1)「[+ - ] \ d \ d:\ d \ d」形式的偏移,如「+02:00」或「-08:00」。請注意,「+00:00」的偏移量意味着與「Z」相同的值。有關更多詳細信息,請閱讀RFC 3339規範:http://tools.ietf.org/html/rfc3339 – steveha 2011-03-14 14:40:19

+0

Python bug:[issue15873:datetime:添加解析RFC 3339日期和時間的功能](http://bugs.python .org/issue15873) – jfs 2013-11-14 00:50:12

+0

相關:[使用strptime將帶有偏移量的時間戳轉換爲datetime obj](http://stackoverflow.com/q/12281975/4279) – jfs 2016-02-25 13:43:18

回答

9

沒有內建,afaik。

feed.date.rfc3339 這是一個Python庫模塊與功能在RFC 3339格式轉換時間戳字符串到Python時間浮點值,並且反之亦然。 RFC 3339是Atom訂閱源聯合格式使用的時間戳格式。

它是BSD許可的。

http://home.blarg.net/~steveha/pyfeed.html

(編輯所以很顯然我沒有寫。:-)

+0

PyFeed完全符合我的需求,提供tf_from_timestamp()函數feed.date.rfc3339 – 2009-12-21 19:46:13

+1

此外,我編寫了PyFeed(和Xe)庫,並且我在這裏討論了StackOverflow,所以如果您有任何疑問,我會很樂意回答。 – steveha 2009-12-21 19:46:13

+0

請注意,PyFeed可用於解析Atom提要。它使用xml.dom.minidom來進行實際的解析,然後將XML樹結構解包爲很好的方便的類。嗯,我應該把Xe和PyFeed放在PyPI上。 – steveha 2009-12-21 19:59:47

8

http://pypi.python.org/pypi/iso8601/似乎能夠解析ISO 8601,這RFC 3339的一個子集,也許這可能是有用,但又是非內置的。

+0

時間浮點數和struct_time不是時區感知的。由於RFC 3339要求與UTC兼容的時區,在Python中意味着非天真的日期時間對象,所以這是目前唯一的理智選擇。 – Tobu 2011-09-16 18:06:35

21

你不包括一個例子,但如果你沒有一個Z-偏移或時區,並假設你不想工期,但只是基本的時間,那麼也許這會適合你:

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) 

strptime()函數被添加到Python 2.5中的日期時間模塊,所以有些人還不知道它在那裏。

編輯:本time.strptime()函數已經存在了一段時間雖然和工程差不多給你一個struct_time值:

>>> 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 
+7

+1使用標準庫的解決方案! – jathanism 2009-12-21 21:39:56

+8

這不起作用 - 不能識別時區的方法不兼容RFC 3339。 – Yarin 2011-12-19 01:02:30

+0

Yarin,很明顯,但你的投訴應該與原始問題中對「RFC 3339」的使用一致,因爲我的回答確實解決了他的實際問題,他注意到他沒有時區... – 2012-01-01 16:08:01

5

feedparser.py提供了強大的/可擴展的方式來解析各種可在現實世界的原子中遇到的日期格式/ RSS提要:

>>> 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) 
+1

這似乎比PyFeed提供的」時間浮點數「要好得多。 – 2010-11-21 15:14:13

+2

cool-NR,如果你有一個時間浮點值,你可以調用'time.gmtime()'並獲得'struct_time'值。用時間浮點值做相對時間要容易得多;從現在開始兩天就是'tf + 2 * seconds_per_day'(其中'seconds_per_day'爲24 * 60 * 60)。 Python的'struct_time'非常適合檢查(一週中的哪一天?),但對於計算來說非常不方便。 – steveha 2011-03-14 14:39:17

+0

鏈接已損壞 - 是否應爲http://code.google.com/p/feedparser/source/browse/trunk/feedparser/feedparser.py? – Yarin 2011-12-19 00:58:00

0

在另一個問題中遇到了令人敬畏的dateutil.parser模塊,並在我的RFC3339問題上嘗試了它,並且它似乎處理我所拋出的所有內容,並且更加完整地回答了此問題中的任何其他響應。

+1

唯一的問題是,它也解析*非日期*值,如「now」 – 2013-02-25 10:54:56

1

試試這個,它工作正常,我

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

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

它不支持數字utc偏移量:'+ HHMM'。第二個例子不是[rfc 3339](https://tools.ietf.org/html/rfc3339#section-5.6);它是[rfc 5322](https://tools.ietf.org/html/rfc5322#section-3.3) – jfs 2015-09-22 23:45:56

3

我與RFC3339 datetime格式的很多努力,但我找到一個合適的解決方案轉換DATE_STRING < => datetime_object在兩個方向。

需要兩個不同的外部模塊,因爲其中一人是隻能夠做轉換在一個方向(不幸):

先安裝:

sudo pip install rfc3339 
sudo pip install iso8601 

則包括:

import datetime  # for general datetime object handling 
import rfc3339  # for date object -> date string 
import iso8601  # for date string -> date object 

因爲不需要記住哪個模塊用於哪個方向,我寫了兩個簡單的輔助函數:

def get_date_object(date_string): 
    return iso8601.parse_date(date_string) 

def get_date_string(date_object): 
    return rfc3339.rfc3339(date_object) 

你的代碼中,你可以方便地使用這樣的:

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!現在你可以很容易地(haha​​)以可用的格式使用你的日期字符串和日期字符串。

1

使用Python 3,您可以使用RegEx將RFC 3339時間戳分解爲其組件。 然後,直接創建日期時間對象,不需要額外的模塊:

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

此示例theads丟失時區或微秒爲「0」,但可能需要額外的錯誤檢查。 乾杯,亞歷克斯

+1

大概,這也可以在Python 2中運行。 – Flimm 2016-08-26 14:19:18

2

如果你使用Django,你可以使用Django的功能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>)