我已经在Django中完成了一些日期模拟问题,并且最后的障碍(我希望)是以下情况。我有一个FakeDate类,它派生自datetime.date
,它会模拟出来。
FakeDate类按预期工作,但是在向FakeDate添加datetime.timedelta
时遇到问题,因为它返回真正的datetime.date
,而不是模拟。这很重要,因为在第三方库的其他地方有一个isinstance(value, datetime.date)
检查,在使用timedelta时总是会失败。
>>> import mock
>>> import datetime
>>>
>>> class FakeDate(datetime.date):
... @classmethod
... def today(cls):
... return cls(1999, 12, 31)
...
>>> FakeDate.today()
FakeDate(1999, 12, 31)
>>> FakeDate(2000, 1, 1)
FakeDate(2000, 1, 1)
>>> FakeDate(1999, 12, 31) + datetime.timedelta(days=1)
datetime.date(2000, 1, 1)
我希望FakeDate + timedelta添加返回一个FakeDate对象而不是datetime.date对象 - 我想这会涉及以某种方式修补timedelta - 但是我如何/在哪里可以做到这一点?
答案 0 :(得分:4)
在__add__
课程中添加FakeDate()
方法:
class FakeDate(datetime.date):
@classmethod
def today(cls):
return cls(1999, 12, 31)
def __add__(self, other):
res = super(FakeDate, self).__add__(other)
return type(self)(res.year, res.month, res.day)
演示:
>>> class FakeDate(datetime.date):
... @classmethod
... def today(cls):
... return cls(1999, 12, 31)
... def __add__(self, other):
... res = super(FakeDate, self).__add__(other)
... return type(self)(res.year, res.month, res.day)
...
>>> FakeDate.today() + datetime.timedelta(days=1)
FakeDate(2000, 1, 1)
请注意,您可以在此处简单地将实际添加委托给datetime.date
课程;我们需要做的就是将结果转换回FakeDate()
实例。
答案 1 :(得分:1)
您只需要在__add__
类中定义FakeDate
方法 - 这是控制+
运算符行为的方法。
import datetime
class FakeDate(datetime.date):
@classmethod
def today(cls):
return cls(1999, 12, 31)
def __add__(self, delta):
# Create a datetime.date object so we don't need to do any calculations
new_date = super(FakeDate, self).__add__(delta)
# Then convert it to FakeDate.
return FakeDate(new_date.year, new_date.month, new_date.day)
# Returns a FakeDate for 2000-01-01
FakeDate.today() + datetime.timedelta(days=1)
请注意,这仅处理fakedate + timedelta
案例。如果您希望timedelta + fakedate
也返回FakeDate
的实例,则还需要定义__radd__
方法(与__add__
相同的代码)。
有关与运营商相关联的__magic_methods__
的详细信息,请参阅http://docs.python.org/2/reference/datamodel.html#emulating-numeric-types。