2017-06-21 10 views
1

Wikidata APIによって与えられた日付の日付比較を行いたいと思います。まずPythonのWikidata APIの日付の比較

しかしI Pythonのdatetimeモジュールを使用するために、私は二つの問題にぶつかった:

  • ウィキデータはジュリアンとグレゴリオ暦の過去や未来に数十億年を超えるまたがる日付、日時を扱います
  • 精度が(9)年以下の場合、datetime.strptimeは管理しない月と日は "00-00"と表示されます。パリについてこのsample queryで例えば

、この日付は日時に変換することができます。

datetime.strptime("+1968-01-01T00:00:00Z","+%Y-%m-%dT%H:%M:%SZ") 
datetime.datetime(1968, 1, 1, 0, 0) 

この1つはできません:

datetime.strptime("+2012-00-00T00:00:00Z","+%Y-%m-%dT%H:%M:%SZ") 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/usr/lib/python3.5/_strptime.py", line 510, in _strptime_datetime 
    tt, fraction = _strptime(data_string, format) 
    File "/usr/lib/python3.5/_strptime.py", line 343, in _strptime 
    (data_string, format)) 
ValueError: time data '+2012-00-00T00:00:00Z' does not match format '+%Y-%m-%dT%H:%M:%SZ' 

は「-0300-00は言うまでもありません-00T00:00:00Z "(300 BCE)

私は単に年の比較を使うことはできません。なぜなら、コモンより前に起こったことa、同じ負の年に複数の日付が存在する可能性があります。

私はこれに対処する最善の方法についてはあまりよく分かりません。私が使用できる別のライブラリがありますか?

+1

日付の比較はどういう意味ですか? 「+ 2012-00-00T00:00:00Z」と「+ 2012-01-01T00:00:00Z」との比較結果は –

+0

となります。日付はクレームに使用される修飾語です。今、ポストの最近の人口が欲しいですが、より一般的な方法にしたいと思います。 –

答えて

2

tl; dr: datetimeはこのようなことを処理できませんので、試してみてください。あなたは文字列を持っていて、それらを保持し、そのように扱います。

文字列として並べ替えることができます(ただし、必要に応じてパッドが必要です)。これにより、 "拡張" ISO8601:2004タイムスタンプのソートが可能になります(標準では00月間および日数は許可されていません)。 python3、このコードを仮定し

import urllib.request,json 
url = urllib.request.urlopen("https://www.wikidata.org/w/api.php?action=wbgetentities&format=json&ids=Q90&props=info%7Caliases%7Clabels%7Cdescriptions%7Cclaims%7Cdatatype%7Csitelinks%2Furls&languages=fr&languagefallback=1&formatversion=2") 
data = json.loads(url.read().decode()) 
P6 = sorted(data['entities']['Q90']['claims']['P6'], key=lambda claim: claim['qualifiers']['P580'][0]['datavalue']['value']['time']) 
for x in P6: 
    print(x['mainsnak']['datavalue']['value']['numeric-id']) 

は、この結果セットを生成:で始まる

  • アイテム:

    1685301 
    947901 
    656015 
    2596877 
    3131449 
    1986521 
    1685102 
    1684642 
    601266 
    677730 
    289303 
    959708 
    2105 
    1685859 
    256294 
    2851133 
    

    さらに、次の2つにあなたのリストを分離することをお勧めしますa -符号

  • アイテム

+記号で始まる続いて、文字列で表さ年の符号なし整数値で、月 - 日時昇順で最初にリストを並べ替える(sort()sorted()guaranteedstableあるとして)、2番目を明示的にソートし、それらを再び連結します。これにより、適切なソートが ISO8601タイムスタンプに署名されます。パディング用として

neg = [x for x in P6 if x['qualifiers']['P580'][0]['datavalue']['value']['time'].startswith('-') ] 
pos = [x for x in P6 if x['qualifiers']['P580'][0]['datavalue']['value']['time'].startswith('+') ] 
neg.sort(key=lambda claim: claim['qualifiers']['P580'][0]['datavalue']['value']['time'][5:]) 
neg.sort(key=lambda claim: claim['qualifiers']['P580'][0]['datavalue']['value']['time'][1:5]) 
pos.sort(key=lambda claim: claim['qualifiers']['P580'][0]['datavalue']['value']['time']) 
P6sorted = neg+pos 

、それが必要とされなければならないあなたはやや「新しい」タイムスタンプの長さを反映するためにソートを変更する必要がありますが、それは(string.rjust()を使用して十分な些細だ。string.zfill()はのための適切なツールではありませんその仕事、あなたが変更している文字列が「T」を有する、数値ではないとして、「Z」、「 - 」、および「:」):さておき、あなたが「したいこととして

maxlength = max(map(lambda claim: len(claim['qualifiers']['P580'][0]['datavalue']['value']['time']), P6)) 
for claim in P6: 
    claim['qualifiers']['P580'][0]['datavalue']['value']['time'] = claim['qualifiers']['P580'][0]['datavalue']['value']['time'][0] + claim['qualifiers']['P580'][0]['datavalue']['value']['time'][1:].rjust(maxlength-1, "0"); 

neg = [x for x in P6 if x['qualifiers']['P580'][0]['datavalue']['value']['time'].startswith('-') ] 
pos = [x for x in P6 if x['qualifiers']['P580'][0]['datavalue']['value']['time'].startswith('+') ] 
neg.sort(key=lambda claim: claim['qualifiers']['P580'][0]['datavalue']['value']['time'][maxlength-16:]) 
neg.sort(key=lambda claim: claim['qualifiers']['P580'][0]['datavalue']['value']['time'][maxlength-22:maxlength-16], reverse=True) 
pos.sort(key=lambda claim: claim['qualifiers']['P580'][0]['datavalue']['value']['time']) 
P6sorted = neg+pos 
for claim in P6sorted: 
    print([claim['mainsnak']['datavalue']['value']['id'],claim['qualifiers']['P580'][0]['datavalue']['value']['time']]) 

飾り付け - 並べ替え - 否定 "(読みやすくするために、シュワルツ変換を実行)。

最後に、ジュリアンとグレゴリオ暦を心配している場合、ユリウス暦の日付をグレゴリオ暦の日付に変換して、国と年に基づいて対応する日数を加えて、上記の方法を適用する必要があります。しかし、ユリウス暦の日付(YYYY) - (MM) - (DD)は、グレゴリオ暦の日付よりも「1日先のようです」よりも前になっているので、あまり心配する必要はありません。