1

我正在使用 Django 应用程序Pyroven,并且正在对其功能进行一些重大的重新设计。作为其中的一部分,我已经开始为它编写一个测试框架,因为目前它没有单元测试。作为背景,它使用剑桥大学 Raven 服务进行身份验证,并为Django提供身份验证后端以利用该服务。

我遇到的问题是测试来自 Raven 的WLS-Response令牌。这形成了一个!分隔值的字符串,其中包括格式中的时间字段:

%Y%m%dT%H%M%SZ

在我的测试代码中,我将其创建为:

raven_issue = datetime.now().strftime('%Y%m%dT%H%M%SZ')

然后将其返回到测试 URL 以供视图处理。问题在于验证这个时间对于验证响应来说并不算太远。验证这一点的代码使用:

def parse_time(t):
    """Converts a time of the form '20110729T123456Z' to a number of seconds
    since the epoch.
    @exception ValueError if the time is not a valid Raven time"""
    time_struct = time.strptime(t, "%Y%m%dT%H%M%SZ")
    return calendar.timegm(time_struct)

现在,当从 datetime.now() 构造函数传递上面的字符串时,对此解析值的验证失败:

# Check that the issue time is not in the future or too far in the past:
if self.issue > time.time() + PYROVEN_MAX_CLOCK_SKEW:
    raise InvalidResponseError("The timestamp on the response is in the future")
if self.issue < time.time() - PYROVEN_MAX_CLOCK_SKEW - PYROVEN_TIMEOUT: 
    raise InvalidResponseError("The response has timed out")

此代码在我的测试中失败,声称响应已超时。PYROVEN_MAX_CLOCK_SKEW和的值PYROVEN_TIMEOUT分别为 2s 和 10s。

这引出了一个问题,在我不理解的时间处理中是否存在一些可变性?如果我在未来 2 小时内放置一个datetime.now()生成的值,datetime.timedelta将其转换为字符串并将其传递给验证,尽管时间戳在未来,但它应该不会失败。为什么会这样,正如对代码的逻辑解读所暗示的那样?

4

1 回答 1

2

datetime.now()您在本地时间(由和 GMT 返回的时间(由 解析)之间感到困惑calendar.timegm()

>>> t = datetime.now().strftime('%Y%m%dT%H%M%SZ')
>>> t
'20120910T232358Z'
>>> calendar.timegm(time.strptime(t, "%Y%m%dT%H%M%SZ"))
1347319438
>>> time.mktime(time.localtime())
1347312258.0
>>> time.mktime(time.strptime(t, "%Y%m%dT%H%M%SZ"))
1347312238.0

结论:使用time.mktime而不是calendar.timegm将您的值转换为时间戳。

于 2012-09-10T21:25:06.527 回答