0

この問題が発生しました。さまざまなWebページからRSSフィードを取得してから、日付順に並べ替える必要があります。xml操作にはxqueryを使用し、rss/xmlの保存にはeXistデータベースを使用しています。これが私のコードです:

for $item in subsequence(collection('/db/bla/user/feed')//item[contains(title, $search)], $start, $num)
                 let $title:= $item/title/text()
                 let $desc:= $item/description/text()
                 let $link := $item/link/text()
                 let $date:= $item/pubDate/text()
                 order by $date

これは動作しません。また、問題はGMTとESTの異なる時間帯にあると想定しているため、$dateによる順序付けは正常に機能しません。助けてください、私はここで立ち往生しています。

前もって感謝します!

編集:

pubDateタグから取得する日付と時刻の形式は次のとおりです。

Mon, 10 Dec 2012 13:32:24 EST

また

Mon, 10 Dec 2012 13:32:24 GMT
4

3 に答える 3

2

$date実際の日付/時刻としてキャストしてみてください。

let $date:= xs:dateTime($item/pubDate/text())

日付/時刻の形式が一貫している場合は、独自のコンバーターを実装できます。あなたのコメントの例で、最も問題を引き起こす2つの部分は、月とタイムゾーンです。月は数値である必要があり、タイムゾーンを同等の UTC オフセットに変換する必要があります。

次に例を示します。

declare variable $months := ('jan','feb','mar','apr','may','jun','jul','aug','sep','oct','nov','dec');
declare variable $timezoneMap := 
    <map>
        <tz>
            <numeric>-05:00</numeric>
            <alpha>est</alpha>
        </tz>
    </map>;

declare function local:formatDate($origdate as xs:string) as xs:dateTime {
    let $dateTokens := tokenize($origdate,' ')  
    let $timezone := $timezoneMap/tz[lower-case($dateTokens[6])=alpha]/numeric/text()
    let $month := string(index-of($months,lower-case($dateTokens[3])))
    let $newDate := concat($dateTokens[4],'-',if (string-length($month)=1) then concat('0',$month) else $month,'-',$dateTokens[2],
                           'T',$dateTokens[5],$timezone)
    return
        xs:dateTime($newDate)
};

次に、次のように関数を使用できます。

let $date:= local:formatDate($item/pubDate)

また、XQuery 3.0 を使用している場合は、タイムゾーンと月のマップを使用できます。

declare namespace map = "http://www.w3.org/2005/xpath-functions/map";
declare variable $months := map{"jan":="01","feb":="02","mar":="03","apr":="04","may":="05","jun":="06",
                                "jul":="07","aug":="08","sep":="09","oct":="10","nov":="11","dec":="12"};
declare variable $timezoneMap := map{"est":="-05:00"};

declare function local:formatDate($origdate as xs:string) as xs:dateTime {
    let $dateTokens := tokenize($origdate,' ')
    let $newDate := concat($dateTokens[4],'-',$months(lower-case($dateTokens[3])),'-',$dateTokens[2],
                           'T',$dateTokens[5],$timezoneMap(lower-case($dateTokens[6])))
    return
        xs:dateTime($newDate)
};
于 2013-01-10T16:59:11.813 に答える
1

XQuery で何らかの日付形式パーサーを構築することは、おそらく最良のアイデアではありません。タイム ゾーンの変換 (さらに悪いことに、夏時間...) はすべて自分で処理する必要があります。

公式の方法: DateTime-Module

eXist DB には、に基づく独自の DateTime-Module がありjava.text.SimpleDateFormatます。このモジュールは、使用する前にコンパイルしてアクティブ化する必要があり、eXists の現在の安定版リリースには含まれていません (ただし、1.4.3 開発者リリースおよびバージョン 2 プレリリースには含まれています)。

警告、システムのデフォルトのロケールを使用しますが、私の場合は英語ではありませんでした (そのため、日付の認識は惨めに失敗しました)。

有効にできた場合(そうでない場合、これはおそらくSO 姉妹サイトであるDatabase Administratorに関する別の質問です)、このコードを実行して、指定された形式で日付を解析できるはずです。

import module namespace datetime = "http://exist-db.org/xquery/datetime";
datetime:parse-dateTime('Mon, 10 Dec 2012 13:32:24 GMT', 'EEE, d MMM yyyy HH:mm:ss Z')

The Dirty Hack: Java とのインターフェイス

古いバージョンの eXist を実行している場合、または他の理由でモジュールを使用できない場合は、Java バインディングを有効にしてconf.xml、この関数を直接呼び出すことができます。

declare namespace sdtf="java:java.text.SimpleDateFormat";
declare namespace date="java:java.util.Date";

(: Parse given date format to java date :)    
let $parse := sdtf:new('EEE, d MMM yyyy HH:mm:ss Z')
(: Output as close to XQuery's xs:dateTime as possible :)
let $format := sdtf:new("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
let $javadate := sdtf:parse($parse, 'Mon, 10 Dec 2012 13:32:24 GMT')
(: Use regex to insert missing ':' and finally cast to xs:dateTime :)
return xs:dateTime(fn:replace(sdtf:format($format, $javadate), '(.*)(\d{2})', '$1:$2'))

ここでも、Java ロケールがデフォルトでない場合は英語に設定することを忘れないでください。

これは、少なくとも Saxon (この Java バインディングを定義したもの) と BaseX (ここで実際にテストしたもの) では正常に動作するはずだと思います。

于 2013-01-11T00:17:26.913 に答える
1

Ryan Grimm の XQuery ベースの Date Parser モジュールを使用できます。これは MarkLogic 用に構築されていますが、小さな変更を加えれば、他のシステムでも動作するはずです。https://github.com/marklogic/commons/blob/master/dates/date-parser.xqyを参照してください。

モジュール状態のコメントとして、サポートされている日付形式は次のとおりです。

  1. 2006 年 6 月 30 日 09:39:08 -0500
  2. 4 月 16 日 13:49:06 2003 +0200
  3. 2003 年 8 月 4 日 11:44:58 EDT
  4. 98 年 1 月 4 日 0:41 EDT
  5. 2004 年 10 月 25 日 17:06:46 -0500
  6. 月、23 9 月 0102 23:14:26 +0900
于 2013-01-11T20:17:06.427 に答える