0

Word文書のOLEストリームからデータを引き出すPythonスクリプトを作成しましたが、OLE2形式のタイムスタンプを人間が読める形式に変換するのに問題があります:(

抽出されたタイムスタンプは 12760233021 ですが、これを 2007 年 3 月 12 日などの日付に変換することはできません。

どんな助けでも大歓迎です。

編集: OK 、2009 年 10 月31 日 10:05:00に作成された Word ドキュメントの 1 つに対してスクリプトを実行しました。OLE DocumentSummaryInformation ストリームの作成日は12901417500です。

別の例として、2009 年 10 月 27 日 15:33:00 に作成された単語 doc は、OLE DocumentSummaryInformation ストリームで 12901091580 の作成日を示します。

これらの OLE ストリームのプロパティに関する MSDN ドキュメントは、http://msdn.microsoft.com/en-us/library/aa380376%28VS.85%29.aspxです。

これらのストリームを引き出す定義を以下に示します。

import OleFileIO_PL as ole

def enumerateStreams(item):
    # item is an arbitrary file
    if ole.isOleFile('%s' % item):
        loader = ole.OleFileIO('%s' % item)
        # enumerate all the OLE streams in the office file
        streams = loader.listdir()
        streamProps = []
        for stream in streams:
            if stream[0] == '\x05SummaryInformation':
                # get all the properties fro the SummaryInformation OLE stream
                streamProps.append(loader.getproperties(stream))
            elif stream[0] == '\x05DocumentSummaryInformation':
                # get all the properties from the DocumentSummaryInformation stream
                streamProps.append(loader.getproperties(stream))
     return streamProps
4

2 に答える 2

2

この質問はかなり古いですが、まだ役に立ちます。最近、OleFileIO_PL を改良して、日付を自動的に Python の datetime に変換することで問題を修正しました。

このページのドキュメント、特に get_metadata と get_properties に関する部分を参照してください: https://bitbucket.org/decalage/olefileio_pl

get_metadata を使用すると、「\x05SummaryInformation」などの標準プロパティ ストリームのすべてのタイムスタンプが Python の日時に変換されます。代わりに get_properties を使用する必要がある場合は、convert_time オプションを使用します。

p = ole.getproperties('specialprops', convert_time=True)

フィリップ。

于 2014-02-06T14:37:49.857 に答える
2

(0) 「2007 年 3 月 12 日または類似」のように明確にしてください: 11 桁の int が 2007 年 3 月 12 日に変換されることを期待しているということですか、それとも「2007 年 3 月 12 日」は単に変換したいフォーマットを伝えることを意図しているのでしょうか。日付を表示しますか?後者の場合、MS Word や OpenOffice.org のワード プロセッシング ガジェットでいくつかのファイルを調べて、期待どおりの結果が得られないでしょうか? 提供されているソリューションが実際に機能することをどのように検証するつもりですか?

(1) 提案されたソリューションの正しい動作をより確実に検証できるように、複数の (OLE、予想される) ペアを提供してください。可能であれば、2000 年 1 月 1 日、2001 年 1 月 1 日、2001 年 1 月 2 日、2001 年 2 月 2 日のような既知の期待値で例を作成できますか?

(2) 「OLE ストリームからデータを引き出す」からは、OLE2 複合ドキュメント ヘッダーにファイル作成などのタイムスタンプが必要かどうか、またはコンテンツに存在するタイムスタンプが必要かどうかは明らかではありません。タイムスタンプを探している場所を教えてください。また、関心のあるタイムスタンプに関連する MS ドキュメントへの参照を提供できれば、非常に役立ちます...確かに、1 つまたは 2 つのイントラ/エクストラによって間接的にそうする場合でも、フォーマットが何であるかを伝える必要があります-ドキュメント ホップ。

(3) それをどのように引き出しているかを示してください -- それはひもですか? 11バイト固定?それとも str(64 ビット フィールドから変換した int の一部)ですか? 変換方法?? 説明と同様に、変換コードを表示します。メモリからコードを再入力しないでください。コピー/貼り付けを使用します。

コメントとしてではなく、質問を編集して、要求された情報を提供してください。

情報を待っている間に更新:

OLE 複合ドキュメント ヘッダーのファイル作成および変更のタイムスタンプは、(1601-01-01T00:00:00 からの秒数) * 10 ** 7 を表す 64 ビットのリトル エンディアン整数のように見えます。

OLE2 データのデータで使用されている DATE 型は、1899-12-30T00:00:00 以降の 64 ビット リトルエンディアン IEEE 754 浮動小数点数 (日とその分数) を表すようです。はい、その日は 31 日ではなく 30 日です。

提供された 2 つの例を調べた後に更新します。

観測された 2 つのタイムスタンプ (現地時間になります) の差は 325920 秒です。

>>> import datetime
>>> t0 = datetime.datetime(2009,10,27,15,33,0)
>>> t1 = datetime.datetime(2009,10,31,10,5,0)
>>> t1-t0
datetime.timedelta(3, 66720)
>>> secs = 3 * 24 * 60 * 60 + 66720
>>> secs
325920

これは、2 つのマジック ナンバーの違いと同じです。

>>> 12901417500 - 1290191580
325920

したがって、魔法の数字は、あるエポックからの秒数を表します...

>>> m1 = 12901417500
>>> days, seconds = divmod(m1, 60*60*24)
>>> epoch = t1 - datetime.timedelta(days, seconds)
>>> epoch
datetime.datetime(1601, 1, 1, 11, 0)

したがって、マジック ナンバーは 1601-01-01T00:00:00Z からの秒数を表し、TZ は UTC から 11 時間離れています。

これらの 2 つのマジック ナンバーは 32 ビットに収まりません ... (a) 1601 年からの秒数として 64 ビットで格納される (約 29 ビットの無駄です!) または (b) (数の100 ナノ秒単位) 1601 以降は予想どおりですが、表示される前に何かが 10**7 で割っています。

あなたが与えたドキュメンテーションリファレンスは、それが型だと言っているだけですVF_FILETIME (UTC)。それをグーグルで検索すると、Windows関数を呼び出してタイムスタンプを操作することに関するいくつかのMSの手がかりが見つかりましたが、私が見た限り定義はありません。しかし、ほとんど同じことを言っている 2 つのサードパーティのメモ (perlmonks と Apache POI プロジェクトから) がありますVT_FILETIME。 1601"""

犯罪現場からの更新:

OleFileIO_PLファイルの読み取りに使用しているようです。唯一のソース ファイルをざっと調べてみると、次のことがわかります。

    elif type == VT_FILETIME:
        value = long(i32(s, offset+4)) + (long(i32(s, offset+8))<<32)
        # FIXME: this is a 64-bit int: "number of 100ns periods
        # since Jan 1,1601".  Should map this to Python time
        value = value / 10000000L # seconds
于 2009-11-30T05:52:12.943 に答える