从datetime对象创建64位值

时间:2014-06-03 20:14:54

标签: python unit-testing python-2.7 datetime

我正在从Active Directory中提取信息,这意味着我正在处理一些COMObjects。其中一个日期存储为64位整数(实际上是两个32位整数)。我已经想出如何使用以下代码将其更改为日期时间对象。

def convert_to_datetime(time_object):
    # http://docs.activestate.com/activepython/2.6/pywin32/html/com/help/active_directory.html
    d = 116444736000000000L #diference between 1601 and 1970
    time_int = (((long(time_object.highpart) << 32) + long(time_object.lowpart)) - d)/10000000
    return datetime.datetime.fromtimestamp(time_int)

现在有了这个,我想为此建立一个单元测试。但是,我似乎无法弄清楚如何从datetime对象生成64位整数。我目前正在做的是我创建了一个复制COMObject的类,它将其值存储为两个32位整数,然后对匹配的日期和整数的值进行硬编码。但是,我想根据“现在”的时间创建这些值。

以下是目前单元测试的内容,即通过。

    def test_convert_to_datetime_for_64bit_int_returns_value(self):
        now_com_time = COMObjectDate(30375774,216380170)
        self.assertEqual(datetime.datetime(2014, 6, 3, 14, 0, 13), AD_AG.convert_to_datetime(now_com_time))

class COMObjectDate:
    def __init__(self, high, low):
        self.highpart = high
        self.lowpart = low

有没有办法从日期时间对象生成两个32位值?

旁注:我意识到我可能已经过度思考了一些,因为我的单元测试确实通过但是我宁愿没有硬编码值,因此测试更强大而且不依赖于值那“只是工作”。

1 个答案:

答案 0 :(得分:2)

我们将从您链接到的文档中引用:

  

活动目录中的时间存储在保留的64位整数中   跟踪已经过的100纳秒间隔的数量   自1601年1月1日起。

因此,将这些部分视为两个32位整数(高和低,添加前导零):

bin(30375774) =

00000001110011110111111101011110

bin(216380170) = 

00001100111001011011001100001010

将它们连接在一起('高部分'和'低部分')以获得64位整数:

0000000111001111011111110101111000001100111001011011001100001010

十进制,即130462956137067274

要获得自1601年1月1日以来经过的的数量,我们必须除以 10000000

130462956137067274 / 10000000 
= 13.046.295.613 seconds since the 1st of january 1601

如果你想构造相应的32位整数部分,简单的日期算术应该反过来:从1601年1月1日开始的秒数开始,乘以10000000并将其中的64位整数分成两位32位零件(可通过位移轻松完成)。

convert_to_datetime方法实现也应该有意义。您现在唯一需要的是datetime.fromtimestamp()方法需要POSIX timestamp,这是一个浮点数(在本例中),包含自epoch以来经过的秒数( 1970年1月1日)。这解释了方法体中存在的基于偏移的计算。

====> 1. Creating a Unix timestamp (seconds since epoch) from a datetime
>>> import time
>>> import datetime
>>> time.mktime(datetime.datetime.now().timetuple())
1401828155.0 

====> 2. Adding the difference in seconds between 01/01/1601 and 01/01/1970 
====> (11644473600 seconds)
>>> 11644473600 + 1401828155
13046301755

====> 3. Multiply by 10000000
>>> 13046301755 * 10000000
130463017550000000

====> 4. Interpret as binary. Add leading zero's until you have 64 bits.
>>> bin(130463017550000000)
'0b111001111011111110110110001011001011001001010111110000000'

====> 5. Split the high part (32 bits) and the low part (32 bits)
>>> ...