4

我在 Django 中解决了一些日期模拟问题,最后的障碍(我希望)是以下情况。我有一个 FakeDate 类,它派生自datetime.date,它模拟出来。

FakeDate 类按预期工作,但是在将 a 添加datetime.timedelta到 FakeDate 时出现问题,因为它返回一个真实的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 - 但我如何/在哪里可以做到这一点?

4

2 回答 2

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()实例。

于 2013-11-29T15:01:00.683 回答
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

于 2013-11-29T15:10:42.720 回答