Frage

Ich habe ein Python-Skript erstellt, das Daten aus OLE-Streams in Word-Dokumenten abruft, habe aber Probleme beim Konvertieren des OLE2-formatierten Zeitstempels in etwas, das für Menschen besser lesbar ist :(

Der herausgezogene Zeitstempel ist 12760233021, aber ich kann ihn beim besten Willen nicht in ein Datum wie den 12. März 2007 oder ähnliches umwandeln.

Jede Hilfe wird sehr geschätzt.

BEARBEITEN:OK, ich habe das Skript über eines meiner Word-Dokumente ausgeführt, das erstellt wurde 31/10/2009, 10:05:00.Das Erstellungsdatum im OLE DocumentSummaryInformation-Stream ist 12901417500.

Ein weiteres Beispiel ist ein Word-Dokument, das am 27.10.2009 um 15:33:00 Uhr erstellt wurde und im OLE-Stream DocumentSummaryInformation das Erstellungsdatum 12901091580 angibt.

Die MSDN-Dokumentation zu den Eigenschaften dieser OLE-Streams finden Sie hier http://msdn.microsoft.com/en-us/library/aa380376%28VS.85%29.aspx

Die Definition, die diese Streams abruft, ist unten angegeben:

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
War es hilfreich?

Lösung

(0) Bitte präzisieren Sie „wie 12. März 2007 oder ähnlich“:Meinen Sie damit, dass Sie erwarten, dass das 11-stellige int in den 12. März 2007 konvertiert wird, oder soll „12. März 2007“ lediglich das Format vermitteln, in dem Sie das Datum anzeigen möchten?Wenn letzteres der Fall ist, können Sie dann nicht die erwarteten Ergebnisse liefern, indem Sie einige Dateien mit MS Word oder dem Textverarbeitungs-Gadget von OpenOffice.org überprüfen?Wie wollen Sie überprüfen, ob die angebotene Lösung tatsächlich funktioniert?

(1) Bitte geben Sie mehr als ein (OLE, erwartetes) Paar an, damit die korrekte Funktionsweise einer vorgeschlagenen Lösung mit größerer Sicherheit überprüft werden kann.Können Sie, wenn möglich, Beispiele mit bekannten erwarteten Werten wie 01.01.2000, 01.01.2001, 02.01.2001, 02.02.2001 erstellen?

(2) Aus „zieht Daten aus OLE-Streams“ ist nicht ersichtlich, ob Sie Zeitstempel für die Dateierstellung usw. im Header des OLE2-Verbunddokuments haben möchten oder ob Sie Zeitstempel möchten, die im Inhalt vorhanden sind.Bitte sagen Sie, WO Sie nach Zeitstempeln suchen.Es wäre auch enorm hilfreich, wenn Sie einen Verweis auf die MS-Dokumentation angeben könnten, die sich auf die Zeitstempel bezieht, an denen Sie interessiert sind ...Sicherlich muss es Ihnen sagen, welches Format es ist, auch wenn es dies indirekt über ein oder zwei Intra-/Extra-Dokument-Hops tut.

(3) Bitte zeigen Sie, WIE Sie das herausziehen – ist es eine Schnur?feste 11 Bytes?Oder ist es str(some int, das Sie aus einem 64-Bit-Feld konvertiert haben)?WIE konvertiert??Zeigen Sie neben einer Beschreibung auch Ihren Conversion-Code an.Geben Sie Ihren Code nicht noch einmal aus dem Gedächtnis ein;Verwenden Sie Kopieren/Einfügen.

Bitte geben Sie die angeforderten Informationen an, indem Sie Ihre Frage bearbeiten, nicht als Kommentare.

Update, während auf Informationen gewartet wird:

Die Zeitstempel für die Dateierstellung und -änderung in einem OLE-Verbunddokument-Header scheinen 64-Bit-Little-Endian-Ganzzahlen zu sein, die (Sekunden seit 1601-01-01T00:00:00) * 10 ** 7 darstellen.

Der in Daten in OLE2-Daten verwendete DATE-Typ scheint ein 64-Bit-Little-Endian-IEEE-754-Float zu sein, das (Tage und einen Bruchteil davon) seit dem 30.12.1899T00:00:00 darstellt.Ja, der Tag ist 30, nicht 31.

Update nach Prüfung der beiden mitgelieferten Beispiele:

Der Unterschied zwischen den beiden beobachteten Zeitstempeln (die in Ihrer Ortszeit vorliegen) beträgt 325920 Sekunden:

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

Dies ist dasselbe wie der Unterschied zwischen den beiden magischen Zahlen:

>>> 12901417500 - 1290191580
325920

Die magischen Zahlen repräsentieren also Sekunden seit einer Epoche ...

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

Die magischen Zahlen stellen also Sekunden seit dem 1601-01-01T00:00:00Z dar und Ihr TZ ist 11 Stunden von UTC entfernt.

Diese beiden magischen Zahlen passen nicht in 32 Bit ...Es sieht so aus, als wäre es entweder (a) seit 1601 in 64 Bit als Sekunden gespeichert (eine Verschwendung von etwa 29 Bit!) oder (b) wie erwartet seit 1601 als (Anzahl von 100-Nanosekunden-Einheiten) gespeichert, aber irgendetwas teilt es um 10**7, bevor Sie es sehen.

In der Dokumentationsreferenz, die Sie angegeben haben, heißt es lediglich, dass es sich um eine handelt VF_FILETIME (UTC) Typ.Beim Googeln finde ich ein paar MS-Hinweise zum Aufrufen von Windows-Funktionen zur Manipulation der Zeitstempel, aber soweit ich gesucht habe, keine Definition.Es gibt jedoch zwei Notizen von Drittanbietern (von Perlmonks und dem Apache POI-Projekt), die fast dasselbe sagen:"""Das sieht aus wie ein Windows VT_FILETIME Datentyp, bei dem es sich um eine 64-Bit-Ganzzahl ohne Vorzeichen handelt, die die Anzahl der seit dem 1. Januar 1601 verstrichenen 100 Nanosekunden darstellt.

Update vom Tatort:

Scheint, als würden Sie es verwenden OleFileIO_PL um die Dateien zu lesen.Ein kurzer Blick in die einzige Quelldatei zeigt Folgendes:

    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

Andere Tipps

Diese Frage ist ziemlich alt, aber immer noch nützlich. Ich OleFileIO_PL vor kurzem verbessert, das Problem zu beheben, indem Daten automatisch zu Python Datetime zu konvertieren.

Sehen Sie die Dokumentation auf dieser Seite, insbesondere die Teile über get_metadata und GET_PROPERTIES: https://bitbucket.org/decalage/olefileio_pl

Wenn get_metadata verwenden, werden alle Zeitstempel in Standard-Eigenschaft Ströme wie ‚\ x05SummaryInformation‘ werden in Python zu konvertierende Zeitangabe. Wenn Sie GET_PROPERTIES müssen stattdessen verwenden, dann die convert_time Option verwenden:

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

Philippe.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top