Python OLE2日期格式转换

2024-05-13 21:58:36 发布

您现在位置:Python中文网/ 问答频道 /正文

我创建了一个python脚本,用于从Word文档中的OLE流中提取数据,但是在将OLE2格式的时间戳转换为更具可读性的内容时遇到了困难:(

取出的时间戳是12760233021,但我一辈子都不能把它转换成2007年3月12日或类似的日期。在

非常感谢任何帮助。在

编辑: 好的,我已经在一个word文档上运行了这个脚本,它创建于2009年10月31日10:05:00。OLE DocumentSummary信息流中的创建日期是1290141750。在

另一个例子是创建于2009年10月27日15:33:00的word doc,在oledocumentsummary信息流中给出了12901091580的创建日期。在

有关这些OLE流属性的MSDN文档是http://msdn.microsoft.com/en-us/library/aa380376%28VS.85%29.aspx

提取这些流的def如下所示:

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

Tags: the文档脚本streamdef时间loaderall
2条回答

(0)请澄清“类似2007年3月12日或类似情况”:您的意思是您希望11位整数转换为2007年3月12日,还是“2007年3月12日”只是为了传达您希望显示日期的格式?如果是后者,你不能用msword或开放式办公室的字处理小工具?您打算如何验证所提供的任何解决方案是否实际有效?在

(1)请给出多个(OLE,预期值)对,以便更可靠地验证任何建议解决方案的正确操作。如果可能,您是否可以创建具有已知预期值的示例,例如01 Jan 2000、01 Jan 2001、02 Jan 2001、02 Feb 2001?在

(2)从“从OLE流中提取数据”中看不出您是希望在OLE2复合文档头中使用文件创建等时间戳,还是希望在内容中显示时间戳。请说出你在哪里搜寻时间戳。如果你能提供一个与你感兴趣的时间戳相关的MS文档的参考,它也会非常有帮助。。。当然,它必须告诉您格式是什么,即使它是通过一个或两个内部/额外的文档跃点间接告诉您的。在

(3)请展示你是怎么拔出来的这是一根绳子吗?修复了11个字节?或者是str(从64位字段转换的一些int)?怎么转化的??除了说明之外,还要显示转换代码。不要从内存中重新键入代码;请使用“复制/粘贴”。在

请通过编辑您的问题,而不是评论来提供所需的信息。在

等待信息时更新:

OLE复合文档头中的文件创建和修改时间戳似乎是64位小端整数,表示(从1601-01-01T00:00:00开始的秒数)*10**7。在

OLE2数据中数据中使用的日期类型似乎是64位的小端IEEE754浮点,表示1899-12-30T00:00:00以来的(天数及其小数)。是的,今天是30,不是31。在

检查提供的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

这与两个神奇数字之间的区别相同:

^{pr2}$

所以这些神奇的数字代表某个时代以来的秒数。。。在

>>> 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小时。在

这两个神奇的数字不适合32位。。。从1601年开始,它以64位作为秒存储(浪费了大约29位!)或者(b)从1601年开始,它被存储为(100纳秒单位的数量),但是在你看到它之前,有东西把它除以10**7。在

您给出的文档引用仅仅说明它是一个VF_FILETIME (UTC)类型。在google上搜索,我发现了一些关于调用Windows函数来操作时间戳的MS线索,但据我所见,没有定义。然而,有两个第三方注释(来自perlmonks和Apache POI项目)说的是完全相同的事情:“这看起来像一个Windows VT_FILETIME数据类型,它是一个64位无符号整数,表示自1601年1月1日以来经过的100纳秒数。”

犯罪现场最新消息:

似乎您正在使用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

这个问题很古老,但仍然有用。我最近改进了OleFileIO_PL,通过将日期自动转换为Python日期时间来解决这个问题。在

请参阅本页上的文档,特别是有关get_元数据和get_属性的部分: https://bitbucket.org/decalage/olefileio_pl

使用get_元数据时,标准属性流(如“\x05SummaryInformation”)中的所有时间戳都将转换为Python datetime。 如果您需要改用get_属性,请使用convert_time选项:

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

菲利普。在

相关问题 更多 >