Konvertierung des Python OLE2-Datumsformats
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
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.